使用Pydantic validator子类设父类字段失败,root_validator可行
子类中Pydantic字段验证器无法修改父类字段的原因分析
核心问题出在Pydantic验证器的执行顺序上:
字段验证器(
@validator/@field_validator)是按字段的定义层级和顺序执行的:父类的字段会先于子类字段完成验证和初始化。
当你在子类中给父类的field1绑定字段验证器时,这个验证器会在父类字段初始化阶段就触发运行。此时子类的field2还没被处理(要么是默认值,要么还没被赋值),所以你在验证器里取len(field2)得到的是field2默认状态的长度(比如空字符串的长度0),而非你实例化时传入的实际值长度,最终导致field1还是保留默认值0。根验证器(Pydantic v1的
@root_validator,v2的@model_validator(mode='after'))则是在所有字段都完成初始化和验证之后才运行的。此时子类的field2已经被正确赋值为你传入的内容,所以能拿到正确的长度去修改field1,得到预期的结果3。
举个实际代码例子更直观(以Pydantic v1为例):
from pydantic import BaseModel, validator, root_validator class Parent(BaseModel): field1: int = 0 class Child(Parent): field2: str = "" # 方法1:字段验证器,无法得到正确结果 @validator('field1') def set_field1(cls, v, values): # 此时field2还没被赋值,values里的field2是空字符串 return len(values.get('field2', '')) # 方法2:根验证器,能得到正确结果 # @root_validator(skip_on_failure=True) # def set_field1_root(cls, values): # values['field1'] = len(values['field2']) # return values # 实例化测试 child = Child(field2="abc") print(child.field1) # 方法1输出0,方法2输出3
如果是Pydantic v2,只需把@validator换成@field_validator,根验证器换成@model_validator(mode='after'),核心逻辑和执行顺序的原理完全一致。
内容的提问来源于stack exchange,提问作者tikka
相关产品推荐
相关产品推荐

