Pydantic模型中如何基于已有字段值创建新字段
Pydantic 模型创建依赖其他字段的计算字段方案
你原有代码的问题很明确:类定义阶段直接写name = last_name属于静态类属性赋值,执行这行代码时last_name只是Pydantic的字段声明对象,不是模型实例化后的实际属性值,最终实例的name既不会被Pydantic识别为模型字段,也无法动态获取对应实例的last_name取值。另外你代码中last_name标注为int类型不符合姓名的常规数据类型,示例中会一并修正。
不同场景的正确实现方式
1. Pydantic V2 官方推荐方案:计算字段装饰器
如果需要字段动态跟随依赖字段更新,且自动参与模型校验、序列化导出,直接用@computed_field装饰器搭配Python内置的@property即可,这是V2版本专门为这类场景设计的能力:
from pydantic import BaseModel, Field, computed_field class Info(BaseModel): first_name: str | None = Field(None) last_name: str | None = Field(None) # 修正原代码last_name的类型错误 @computed_field @property def name(self) -> str | None: # 可自定义任意取值逻辑,比如拼接姓名:return f"{self.first_name} {self.last_name}" return self.last_name
使用时不管是直接访问实例的.name属性,还是调用model_dump()、model_json_schema()等方法,name字段都会正常输出,修改实例的last_name值后name会同步更新。
2. Pydantic V1 兼容方案:属性+模型配置
如果使用V1版本,没有computed_field装饰器,可以直接用Python原生@property实现动态取值,再通过模型配置让属性参与序列化:
from pydantic import BaseModel, Field class Info(BaseModel): first_name: str = Field(None) last_name: str = Field(None) @property def name(self): return self.last_name class Config: keep_untouched = (property,) orm_mode = True
3. 固定值场景:校验器预赋值
如果希望name在实例化时就固化取值,后续不随last_name的修改同步变化,可以提前声明name字段,通过模型校验器在实例化阶段完成赋值:
from pydantic import BaseModel, Field, model_validator class Info(BaseModel): first_name: str | None = Field(None) last_name: str | None = Field(None) name: str | None = Field(None) # 必须提前声明字段 @model_validator(mode="after") def assign_name(self): self.name = self.last_name return self
注意:这种方案下
name是独立存储的普通字段,实例创建完成后修改last_name不会自动更新name的值,仅适合取值固定不需要动态联动的场景。
内容的提问来源于stack exchange,提问作者Victor
相关产品推荐
相关产品推荐

