为何Pydantic构造器仅接受model_dump?实例传入报错排查
Pydantic实例传入时的验证错误及解决方法
错误信息
> part: PartOut = PartOut(type="battery", position="l", correlation_timestamp=datetime.now().isoformat(), kpis=kpis) E pydantic_core._pydantic_core.ValidationError: 1 validation error for PartOut E kpis E Input should be a valid dictionary or instance of KpiValues [type=model_type, input_value=KpiValues(values=[KPIValu...hase=None, stage=None)]), input_type=KpiValues]
对象构造代码
kpi: KPIValue = KPIValue(name="somthin'", value=7, timestamp=datetime.now().isoformat()) kpis: KpiValues = KpiValues(values=[kpi]) # 创建包含单个KPI的部件对象 part: PartOut = PartOut(type="battery", position="l", correlation_timestamp=datetime.now().isoformat(), kpis=kpis)
相关Pydantic类定义
class PartOut(BaseModel): # 省略其他字段... kpis: KpiValues = Field(..., alias='kpis') # 其他字段的验证器 @field_validator('type','kpis', mode='before') def convert_none_to_empty_list(cls, v): return v if v is not None else [] model_config = ConfigDict(use_enum_values = True, arbitrary_types_allowed = True, from_attributes = True) class KpiValues(BaseModel): """ 该类表示某个部件在某一时刻的所有KPI值,用于数据库的JSON列存储结构。 """ values: list[KPIValue]
问题原因
问题出在PartOut中针对kpis字段的**mode='before'验证器**。这个验证器会在Pydantic执行类型检查前运行,当传入KpiValues实例时,验证器直接返回该实例,但mode='before'的特性会让Pydantic把这个返回值当作原始输入重新解析,导致它误将已有的模型实例当成普通输入处理,最终触发类型验证错误。
调用model_dump()能正常运行,是因为把模型实例转成了字典,符合Pydantic在验证器之后对原始输入的解析预期。
无需调用model_dump()的解决方法
方案1:移除验证器中对kpis的处理
kpis是KpiValues模型类型,将None转为空列表本身就不符合类型要求,直接把kpis从验证器的字段列表中移除即可:
@field_validator('type', mode='before') def convert_none_to_empty_list(cls, v): return v if v is not None else []
方案2:修改验证器逻辑适配模型类型
如果需要保留对kpis的None处理,调整逻辑,确保输入为KpiValues实例时直接返回,None时返回合法的KpiValues实例(而非空列表):
@field_validator('type','kpis', mode='before') def handle_none_values(cls, v, info): if info.field_name == 'type': return v if v is not None else [] elif info.field_name == 'kpis': return v if v is not None else KpiValues(values=[])
内容的提问来源于stack exchange,提问作者dermoritz
相关产品推荐
相关产品推荐

