You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 11:58:11