Pydantic带pre=True的root_validator接收字典而非输入对象问题
Pydantic中pre=True的root_validator无法检测BaseModel实例的原因及解决方法
问题原因
Pydantic的parse_obj方法处理输入时,会自动将传入的BaseModel实例转换为字段字典(调用实例的dict()方法)。无论是否设置pre=True,root_validator接收的都是转换后的字典,而非原始的A实例,这就是isinstance(values, A)判断始终不生效的核心原因。
解决方法
方法一:重写parse_obj提前拦截A实例
在B类中重写parse_obj类方法,优先判断输入是否为A实例,直接完成结构转换后返回,否则调用父类默认逻辑:
from pydantic import BaseModel class A(BaseModel): a: int b: str class B(BaseModel): c: int d: str @classmethod def parse_obj(cls, obj): if isinstance(obj, A): return cls(c=obj.a, d=obj.b) return super().parse_obj(obj) if __name__ == '__main__': a = A(a=1, b='2') b = B.parse_obj(a) print(b) # 输出: c=1 d='2'
方法二:在root_validator中检测字典特征转换
若不想重写parse_obj,可通过检测字典中A的特征字段(如a和b)来识别并转换结构:
from pydantic import BaseModel, root_validator class A(BaseModel): a: int b: str class B(BaseModel): c: int d: str @root_validator(pre=True) def parse_a_obj(cls, values): if 'a' in values and 'b' in values: return {'c': values['a'], 'd': values['b']} return values if __name__ == '__main__': a = A(a=1, b='2') b = B.parse_obj(a) print(b) # 输出: c=1 d='2'
补充说明
如果A和B结构更复杂,方法一的转换逻辑可扩展为批量映射(比如利用obj.dict()匹配字段);方法二的字段检测也可优化为更精准的判断(如校验A的所有字段是否存在于输入字典中)。
内容的提问来源于stack exchange,提问作者Atai Ambus
相关产品推荐
相关产品推荐

