Pydantic 1.9.1:如何避免验证器中‘if field in values’的代码模式?
问题:Pydantic验证器避免KeyError同时保留字段错误提示
代码示例
两个Pydantic模型及测试字典如下:
from pydantic import BaseModel, StrictStr, validator class A(BaseModel): field1: StrictStr field2: StrictStr @validator('field2', always=True) def check_field2_not_dupliated(cls, field2, values): if field2 == values['field1'] + 'x': raise ValueError(f'{field2=} is the same as field1!') return field2 class B(BaseModel): field1: StrictStr field2: StrictStr @validator('field2', always=True) def check_field2_not_dupliated(cls, field2, values): if 'field1' in values: if field2 == values['field1'] + 'x': raise ValueError(f'{field2=} is the same as field1!') return field2 d = { 'field1': 1, 'field2': 'hello' }
调用结果对比
- 调用
A.parse_obj(d)时,因field1验证失败但field2验证器仍执行,触发KeyError:
> A.parse_obj(d) 5 @validator('field2', always=True) 6 def check_field2_not_dupliated(cls, field2, values): ----> 7 if field2 == values['field1'] + 'x': 8 raise ValueError(f'{field2=} is the same as field1!') 9 return field2 KeyError: 'field1'
- 调用
B.parse_obj(d)时,因额外判断了field1是否存在,能正常抛出field1的类型错误:
> B.parse_obj(d) ValidationError: 1 validation error for B field1 str type expected (type=type_error.str)
需求
希望保持A类的代码风格(无需在field2验证器中添加if 'field1' in values判断),同时能得到B类那样的字段错误提示,即让Pydantic检测到field1输入无效时直接抛出错误,避免进入field2验证器触发KeyError。
解决方案
给field2的验证器添加skip_on_failure=True参数:
class A(BaseModel): field1: StrictStr field2: StrictStr @validator('field2', always=True, skip_on_failure=True) def check_field2_not_dupliated(cls, field2, values): if field2 == values['field1'] + 'x': raise ValueError(f'{field2=} is the same as field1!') return field2
原理
skip_on_failure=True参数会让Pydantic在values中依赖的字段(此处为field1)验证失败时,跳过当前验证器的执行。当field1输入数字1时,StrictStr的类型验证先失败,field2的验证器直接跳过,不会执行到访问values['field1']的代码,最终抛出field1的类型错误,和B类效果一致,同时保持了代码简洁性。
内容的提问来源于stack exchange,提问作者extremeaxe5
相关产品推荐
相关产品推荐

