如何在Pydantic中为多类型字段配置自定义验证类
解决方案
要实现你的需求,核心是让CarModel和BikeModel各自携带自定义验证逻辑,然后在MyModel中用Union声明字段类型即可。Pydantic会自动根据输入数据匹配对应的子模型,并触发该模型的验证规则。
步骤1:定义带自定义验证的子模型
先分别实现CarModel和BikeModel,为它们添加各自的验证器:
from pydantic import BaseModel, field_validator class CarModel(BaseModel): brand: str door_count: int @field_validator('door_count') def check_door_count(cls, v): if v not in [2, 4]: raise ValueError('汽车门数只能是2或4') return v class BikeModel(BaseModel): brand: str has_basket: bool @field_validator('has_basket') def check_basket(cls, v): if not isinstance(v, bool): raise ValueError('是否有车筐必须是布尔值') return v
步骤2:在主模型中使用Union类型
直接用Union[CarModel, BikeModel]声明my_field,Pydantic会自动尝试将输入解析为其中一个模型,并执行对应模型的验证:
from typing import Union from pydantic import BaseModel class MyModel(BaseModel): my_field: Union[CarModel, BikeModel]
测试验证逻辑
测试不同输入的情况:
# 合法的汽车输入 car_input = {"my_field": {"brand": "Toyota", "door_count": 4}} car_model = MyModel(**car_input) print(car_model) # 输出: my_field=CarModel(brand='Toyota', door_count=4) # 非法的汽车输入(门数错误) try: invalid_car = MyModel(**{"my_field": {"brand": "BMW", "door_count": 3}}) except ValueError as e: print(e) # 输出: 1 validation error for MyModel # my_field.door_count # 汽车门数只能是2或4 (type=value_error) # 合法的自行车输入 bike_input = {"my_field": {"brand": "Giant", "has_basket": True}} bike_model = MyModel(**bike_input) print(bike_model) # 输出: my_field=BikeModel(brand='Giant', has_basket=True)
优化:使用鉴别器避免歧义
如果两个子模型的字段有重叠,Pydantic可能无法准确判断该用哪个模型解析,这时可以用**鉴别器(Discriminator)**指定一个区分字段:
from pydantic import BaseModel, field_validator, Field from typing import Literal, Union class CarModel(BaseModel): type: Literal['car'] brand: str door_count: int @field_validator('door_count') def check_door_count(cls, v): if v not in [2, 4]: raise ValueError('汽车门数只能是2或4') return v class BikeModel(BaseModel): type: Literal['bike'] brand: str has_basket: bool @field_validator('has_basket') def check_basket(cls, v): if not isinstance(v, bool): raise ValueError('是否有车筐必须是布尔值') return v class MyModel(BaseModel): my_field: Union[CarModel, BikeModel] = Field(discriminator='type')
这样Pydantic会根据type字段的值直接匹配对应的模型,避免解析歧义。
内容的提问来源于stack exchange,提问作者user22624778
相关产品推荐
相关产品推荐

