创建具有 ID 的对象并填充其他字段
Creating objects with ID and populating other fields
我想构造一个只有ID的Pydantic对象,然后根据ID填充其他字段
我尝试了两种不同的方法,validator 和 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'}
]
解决方案 1:
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 或其他对象填充字段?
__post_init__
不存在,我认为您将其与数据类混淆了。
Pydantic 验证应该在您创建模型对象时进行一次。尽管您可以使用 Config.validate_assignment
.
解决此问题
有两种解决方法:
- 仅使用
id
创建每个模型,然后使用属性分配来设置其他字段。这会更慢,我认为这是错误的做法。
- 在您拥有创建模型所需的所有数据之前不要创建模型。我建议这是最好的方法。
我在 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)
我想构造一个只有ID的Pydantic对象,然后根据ID填充其他字段
我尝试了两种不同的方法,validator 和 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'}
]
解决方案 1:
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 或其他对象填充字段?
__post_init__
不存在,我认为您将其与数据类混淆了。
Pydantic 验证应该在您创建模型对象时进行一次。尽管您可以使用 Config.validate_assignment
.
有两种解决方法:
- 仅使用
id
创建每个模型,然后使用属性分配来设置其他字段。这会更慢,我认为这是错误的做法。 - 在您拥有创建模型所需的所有数据之前不要创建模型。我建议这是最好的方法。
我在 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)