Pydantic V2:嵌套模型下传递错误列表实现批量校验
嵌套模型统一收集校验错误方案
针对你的嵌套模型校验需求,不需要手动传递错误列表给子模型,可通过以下方式实现全层级错误统一收集:
核心思路
- 每个模型自身维护错误列表(用私有属性或排除字段避免序列化)
- 实例创建完成后(通过
model_validator(mode='after'))执行校验逻辑,将错误存入自身错误列表 - 上层模型遍历子模型实例,收集所有子级错误并合并到自身错误列表中
代码示例
基础导入
from pydantic import BaseModel, model_validator, PrivateAttr from typing import List
子模型定义(含校验逻辑)
class Child(BaseModel): field2: str # 用私有属性存储错误,不会被序列化 _errors: List[str] = PrivateAttr(default_factory=list) @model_validator(mode='after') def validate_child_fields(self): # 校验field2长度 if len(self.field2) < 3: self._errors.append(f"field2长度不能小于3,当前值: {self.field2}") # 校验field2是否为纯字母 if not self.field2.isalpha(): self._errors.append(f"field2必须为纯字母,当前值: {self.field2}") return self
父模型定义(含子模型错误收集)
class Parent(BaseModel): field1: List[Child] _errors: List[str] = PrivateAttr(default_factory=list) @model_validator(mode='after') def validate_parent_and_collect_child_errors(self): # 收集所有子模型的错误 for idx, child in enumerate(self.field1): if child._errors: # 为子错误添加层级前缀,方便定位 self._errors.extend([f"field1[{idx}].{err}" for err in child._errors]) # 父模型自身的校验逻辑 if len(self.field1) == 0: self._errors.append("field1不能为空列表") return self
测试使用
# 构造含多个错误的测试数据 test_data = { "field1": [ {"field2": "ab"}, {"field2": "123"}, {"field2": "abc"} ] } # 实例化模型(不会抛出异常) parent = Parent(**test_data) # 获取所有层级的错误 print(parent._errors) # 输出: # ['field1[0].field2长度不能小于3,当前值: ab', 'field1[1].field2必须为纯字母,当前值: 123', 'field1[1].field2长度不能小于3,当前值: 123']
扩展到更多层级
如果存在更深的嵌套模型(如孙模型),只需遵循相同逻辑:
- 孙模型定义私有错误列表和after模式的校验器
- 子模型在自身的校验器中遍历孙模型实例,收集错误并添加前缀
- 父模型继续收集子模型的错误即可
替代方案:用排除字段存储错误
如果不想用私有属性,也可以用Field(exclude=True)定义错误字段,效果类似:
from pydantic import Field class Child(BaseModel): field2: str errors: List[str] = Field(default_factory=list, exclude=True) @model_validator(mode='after') def validate_child_fields(self): if len(self.field2) < 3: self.errors.append(f"field2长度不能小于3,当前值: {self.field2}") return self
内容的提问来源于stack exchange,提问作者Christian Haag
相关产品推荐
相关产品推荐

