【问题标题】:Creating objects with ID and populating other fields创建具有 ID 的对象并填充其他字段
【发布时间】:2020-06-26 23:06:19
【问题描述】:

我想只用 ID 构造一个 Pydantic 对象,然后根据 ID 填充其他字段。
我尝试了 2 种不同的方法,验证器和 post init。也没有工作,所以。

常用代码:

from pydantic import BaseModel, validator

obj_list = [
    {'id': 1, 'name': 'a', 'desc': 'desc1'},
    {'id': 2, 'name': 'b', 'desc': 'desc2'},
    {'id': 3, 'name': 'c', 'desc': 'desc3'}
]

解决方案一:

class Obj(BaseModel):
    id: int
    name: str = None
    desc: str = None

    @validator('id')
    def validate_exists(cls, v):
        items = [h for h in obj_list if h['id'] == v]
        if len(items) == 0:
            raise ValueError('id doesnt exist')
        return v

    def __post_init__(self):
        item = [h for h in obj_list if h['name'] == v][0]
        self.name = item['name']
        self.desc = item['desc']

Obj(id=1)
# <Obj id=1 name=None desc=None>

解决方案2:

class Obj(BaseModel):
    name: str = None
    desc: str = None
    id: int

    @validator('id')
    def validate_exists(cls, v, values):
        items = [h for h in obj_list if h['id'] == v]
        if len(items) == 0:
            raise ValueError('id doesnt exist')
        item = items[0]
        values['name'] = item['name']
        values['desc'] = item['desc']
        return v

Obj(id=1)
# <Obj name=None desc=None id=1>

我觉得这是可行的。我阅读了 Pydantic 和 FastApi 的文档,但找不到与此相关的任何内容。 那么,如何仅使用 ID 构造对象,然后使用 DB 或其他对象填充字段?

【问题讨论】:

    标签: python fastapi pydantic


    【解决方案1】:

    __post_init__ 不存在,我认为您对数据类感到困惑。

    Pydantic 事物验证应该在您创建模型对象时进行一次。尽管您可以使用 Config.validate_assignment 解决此问题。

    有两种解决方案:

    1. 仅使用id 创建每个模型,然后使用属性分配设置其他字段。这会更慢,我认为是错误的方法。
    2. 在拥有创建模型所需的所有数据之前,不要创建模型。我建议这是最好的方法。

    【讨论】:

      【解决方案2】:

      我在 pydantic 中使用 root_validator 解决了这个问题。

      from pydantic import BaseModel, root_validator
      
      obj_list = [
          {'id': 1, 'name': 'a', 'desc': 'desc1'},
          {'id': 2, 'name': 'b', 'desc': 'desc2'},
          {'id': 3, 'name': 'c', 'desc': 'desc3'}
      ]
      class Obj(BaseModel):
          id: int
          name: str = None
          desc: str = None
      
          @root_validator(pre=True)
          def validate_exists(cls, values):
              if 'id' not in values:
                  raise ValueError("id doesn't exist in the fields")
              items = [h for h in obj_list if h['id'] == values['id']]
              if len(items) == 0:
                  raise ValueError(f"there is no obj with id {values['id']}")
              return items[0]
      
      Obj(id=1)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-23
        • 1970-01-01
        • 2015-05-26
        • 1970-01-01
        相关资源
        最近更新 更多