在PUDNIC模型中验证子对象的过程中,是否可以使用包含对象的属性?

给定json数据:

# example.json

{
    "multiplier": 5,
    "field_1": {
        "value": 1
    },
    "field_2": {
        "value": 2
    }
}

以及相应的皮丹蒂克模型:

# example.py

from pydantic import BaseModel, validator

class Item(BaseModel):
    value: int

class Container(BaseModel):
    multiplier: int
    field_1: Item
    field_2: Item

在验证Item个值的过程中,是否可以使用Container对象的multiplier属性?例如,我想在运行时对Item执行类似的操作:

class Item(BaseModel):
    value: int

    @validator("value")
    @classmethod
    def validate_value(cls, value):
        return value # * multiplier  # <--- can I get access to Container's multiplier here?

但我不能确定在这种情况下是否有可能获得Container.multiplier的值?

在我的实际用例中,嵌套要深得多,因此我不希望验证器位于Container级别,因为访问变得相当复杂,但我也不想在项级别向下复制multiplier值?在这种类型的模型中,有没有办法在对象层次 struct 中上下传递参数?

推荐答案

最简单的方法是在父级而不是子级上执行验证:

from pydantic import BaseModel, validator

class Item(BaseModel):
    value: int

class Container(BaseModel):
    multiplier: int
    field_1: Item
    field_2: Item


    @validator("field_1", "field_2")
    def validate_value(cls, v, values):
        """Validate each item"""
        m = values["multiplier"]

如果要在子级上定义验证器,可以创建一个函数,然后从父级调用验证函数:

class Item(BaseModel):
    value: int

    @classmethod
    def validate_value(cls, v, **kwargs):
        """Validate each item"""
        m = kwargs.get("multiplier")

        if m * v.value < 10:
            raise ValueError

        return v


class Container(BaseModel):
    multiplier: int
    field_1: Item
    field_2: Item

    @validator("field_1", "field_2", pre=False)
    def validate_items(cls, v, values):
        return Item.validate_value(v, **values)

另一种方法是将multiplier作为private model attribute传递给子对象,然后子对象可以使用PYDANIC验证函数,但您仍然需要动态赋值给子对象:

from pydantic import BaseModel, Field, validator


class Item(BaseModel):
    multiplier: int  # exclude from parent serialization, workaround for validation
    value: int

    @validator("value", pre=False)
    def validate_value(cls, v, values):
        """Validate each item"""
        m = values["multiplier"]

        if m * v < 10:
            raise ValueError

        return v


class Container(BaseModel):
    multiplier: int
    field_1: Item = Field(..., exclude={'multiplier'})
    field_2: Item = Field(..., exclude={'multiplier'})

    @validator("field_1", "field_2", pre=True)
    def validate_items(cls, v, values):
        
        # Construct from a value, another workaround
        if isinstance(v, int):
            return Item(value=v, multiplier=values["multiplier"])
        
        elif isinstance(v, Item):
            return Item(value=v.value, multiplier=values["multiplier"])


if __name__ == '__main__':

    c = Container(
        multiplier=1,
        field_1=11,
        field_2=22
    )

Python相关问答推荐

Pandas或pyspark跨越列创建

Python tkinter关闭第一个窗口,同时打开第二个窗口

将数组操作转化为纯numpy方法

如何确保Flask应用程序管理面板中的项目具有单击删除功能?

单击Cookie横幅错误并在Selenium中启用搜索栏

如何以实现以下所述的预期行为的方式添加两只Pandas pyramme

Pandas使用过滤器映射多列

自定义新元未更新参数

如何使用PyTest根据self 模拟具有副作用的属性

具有2D功能的Python十六进制图

如何终止带有队列的Python进程?+ 队列大小的错误?

Python中使用时区感知日期时间对象进行时间算术的Incredit

Python在tuple上操作不会通过整个单词匹配

使用numpy提取数据块

如何在虚拟Python环境中运行Python程序?

NP.round解算数据后NP.unique

如何使用Python以编程方式判断和检索Angular网站的动态内容?

删除marplotlib条形图上的底边

try 检索blob名称列表时出现错误填充错误""

matplotlib + python foor loop