Pydantic - 在验证之前更改嵌套模型中的数据

问题描述 投票:0回答:1

我有一个带有 pydantic 的嵌套对象的小例子。

from typing import Dict
from pydantic import BaseModel, Field, ValidationError

class UserType(BaseModel):
    name: str = Field(min_length=1)
    type: str = Field(min_length=1)

class AppConfig(BaseModel):
    key1: int = Field(gt=0)
    objects: Dict[str, UserType]

try:
    data = {
        "key1": 1,
        "objects": {
            "type1": {
                "name": "Name 2",
            },
            "type2": {
                "name": "Name 1"
            }
        }
    }
    c = AppConfig(**data)
    print(c.model_dump_json())
except ValidationError as e:
    print(e)

这显然失败了,因为

type
未在
UserType
模型中设置。我的目标是在实际验证之前使用
UserType.type
字典中的关联键以某种方式设置每个
objects
。比如:

  • 我将数据传递给模型
  • 模型验证主键
  • 在验证嵌套对象之前,它会将 dict 键复制为
    type = key
    内部数据,然后传递给 UserType 模型

这可以通过

pydantic
以某种方式实现吗?

我知道我可以在将数据传递到主模型之前完成所有这些操作,但我想知道这在

pydantic
模型中是否可行。

我也尝试过使用这样的

model_post_init()
方法:

from typing import Dict
from pydantic import BaseModel, Field, ValidationError

class UserType(BaseModel):
    name: str = Field(min_length=1)
    type: str = Field(min_length=1)

class AppConfig(BaseModel):
    key1: int = Field(gt=0)
    objects: Dict[str, UserType]

    def model_post_init(self, __context) -> None:
        values = self.dict()
        for obj_type, obj in values["objects"].items():
            print(obj, obj_type)
            obj["type"] = obj_type

try:
    data = {
        "key1": 1,
        "objects": {
            "type1": {
                "name": "Name 2",
                #"type": "t"
            },
            "type2": {
                "name": "Name 1",
                #"type": "t"
            }
        }
    }
    c = AppConfig(**data)
    print(c.model_dump_json())
except ValidationError as e:
    print(e)

但是这个方法是在验证之后执行的,并且之前验证失败了。还尝试在数据负载中设置一些虚拟类型值,然后在

model_post_init()
中覆盖它,但这根本不起作用,模型只有类型的原始虚拟值。

python validation pydantic
1个回答
0
投票

您可以在验证之前使用

field_validator
mode=before
字段更新对象数据:
objects

© www.soinside.com 2019 - 2024. All rights reserved.