如何在Pydantic V2中用model_validate()为嵌套模型传递字段?
问题描述
现有SQLAlchemy数据库模型:
class User(Base): __tablename__ = "users" id: Mapped[int] = mapped_column(sa.Integer(), primary_key=True) username: Mapped[str | None] = mapped_column(sa.String(64), nullable=True, index=True) email: Mapped[str | None] = mapped_column(sa.String(128), nullable=True)
尝试使用以下Pydantic V2模型序列化用户对象:
class PrivateDataSerializer(BaseModel): model_config = ConfigDict(from_attributes=True) username: str | None email: str | None class ProfileSerializer(BaseModel): model_config = ConfigDict(from_attributes=True) id: int private_data: PrivateDataSerializer
已将username和email字段放入嵌套的PrivateDataSerializer中,目标是通过ProfileSerializer.model_validate(user)加载用户对象,但无法正确配置private_data的字段映射。此前在Django DRF中,可通过为嵌套模型指定source="*"实现该需求:
class PrivateDataSerializer(serializers.ModelSerializer): class Meta: model = User fields = ["username", "email"] class ProfileSerializer(serializers.ModelSerializer): private_data = PrivateDataSerializer(source="*") class Meta: model = User fields = ["id", "private_data"]
请问如何在Pydantic V2中实现相同效果?
解决方案
在Pydantic V2中,可以通过模型验证器或计算字段实现类似DRF中source="*"的效果,核心是让嵌套模型直接从整个用户对象中提取所需字段。
方法一:前置模型验证器
通过@model_validator(mode='before')在验证流程启动前,将原始用户对象赋值给private_data字段,让嵌套模型自动解析所需字段:
from pydantic import model_validator class PrivateDataSerializer(BaseModel): model_config = ConfigDict(from_attributes=True) username: str | None email: str | None class ProfileSerializer(BaseModel): model_config = ConfigDict(from_attributes=True) id: int private_data: PrivateDataSerializer @model_validator(mode='before') def populate_private_data(cls, data): # 将整个用户对象/数据字典传递给private_data字段 data['private_data'] = data return data
使用时直接调用ProfileSerializer.model_validate(user)即可,private_data会自动从用户对象中提取username和email。
方法二:计算字段(更简洁)
利用Pydantic V2的@computed_field特性,自动基于当前关联的用户对象生成嵌套模型实例:
from pydantic import computed_field, ConfigDict class PrivateDataSerializer(BaseModel): model_config = ConfigDict(from_attributes=True) username: str | None email: str | None class ProfileSerializer(BaseModel): model_config = ConfigDict(from_attributes=True) id: int @computed_field def private_data(self) -> PrivateDataSerializer: # 针对SQLAlchemy对象,直接传入原始实例;针对字典输入则解构传入 if hasattr(self, '__pydantic_instance__'): return PrivateDataSerializer.model_validate(self.__pydantic_instance__) return PrivateDataSerializer(**self.__dict__)
这种方式无需手动修改验证流程,通过计算字段自动生成嵌套数据,代码更简洁直观。
内容的提问来源于stack exchange,提问作者goedwig
相关产品推荐
相关产品推荐

