如何修改Pydantic默认映射,实现嵌套Schema的ORM对象转换?
Pydantic嵌套Schema自动映射ORM模型解决方案
背景与需求
现有SQLAlchemy ORM模型:
class Building(Base): id = Column(Integer, primary_key=True) name = Column(String) street = Column(String) city = Column(String) post_code = Column(String)
原Pydantic Schema直接平映射ORM字段可正常运行:
class BuildingOutSchema(BaseModel): id: int name: str street: str city: str post_code: str class Config: orm_mode = True # 调用示例 company = db.query(Company).get(1) return CompanyOutSchema.from_orm(company)
期望将地址相关字段嵌套为AddressSchema,且无需手动循环映射(该Schema会作为列表字段用于其他模型):
class AddressSchema(BaseModel): street: str city: str post_code: str class BuildingOutSchema(BaseModel): id: int name: str address: AddressSchema class Config: orm_mode = True # 期望直接生效的调用 company = db.query(Company).get(1) return CompanyOutSchema.from_orm(company)
可行解决方案
方案1:Pydantic v2 计算字段(推荐)
利用Pydantic v2的computed_field特性,自动从ORM字段组装嵌套Schema:
from pydantic import BaseModel, computed_field class AddressSchema(BaseModel): street: str city: str post_code: str class BuildingOutSchema(BaseModel): id: int name: str class Config: orm_mode = True @computed_field @property def address(self) -> AddressSchema: return AddressSchema( street=self.street, city=self.city, post_code=self.post_code )
此方案无需额外配置,from_orm会自动识别ORM模型的平级字段,通过计算字段生成嵌套的address对象,列表场景下直接用list[BuildingOutSchema].from_orm(query_result)即可批量转换。
方案2:Validator字段填充(兼容v1/v2)
通过@validator在验证阶段自动构建嵌套字段:
from pydantic import BaseModel, validator class AddressSchema(BaseModel): street: str city: str post_code: str class BuildingOutSchema(BaseModel): id: int name: str address: AddressSchema class Config: orm_mode = True @validator('address', pre=True, always=True) def build_address(cls, v, values): # 从平级字段中提取值组装AddressSchema return AddressSchema( street=values.get('street'), city=values.get('city'), post_code=values.get('post_code') )
pre=True确保在字段验证前执行,always=True保证即使没有传入address也会触发,完美适配ORM模型的平级字段结构。
方案3:重写from_orm方法
直接控制ORM到Schema的转换逻辑,适合复杂场景:
class AddressSchema(BaseModel): street: str city: str post_code: str class BuildingOutSchema(BaseModel): id: int name: str address: AddressSchema class Config: orm_mode = True @classmethod def from_orm(cls, obj): return cls( id=obj.id, name=obj.name, address=AddressSchema( street=obj.street, city=obj.city, post_code=obj.post_code ) )
重写后from_orm会直接按自定义逻辑转换ORM对象,列表场景下同样无需手动循环,Pydantic会自动迭代处理。
内容的提问来源于stack exchange,提问作者Ruuza
相关产品推荐
相关产品推荐

