如何实现Pydantic对枚举基类SpecialEnum子类实例的验证?
解决方法
方法一:自定义字段验证器(Pydantic v2)
给MyModel添加自定义验证器,直接检查传入值是否是SpecialEnum子类的实例,绕过Pydantic默认的枚举实例化逻辑:
from pydantic import BaseModel, field_validator from enum import Enum class SpecialEnum(Enum): def do_stuff(self): # 自定义业务逻辑 pass class MySpecialEnum(SpecialEnum): A = 1 B = 2 class MyModel(BaseModel): my_field: SpecialEnum @field_validator('my_field') def check_special_enum_subclass(cls, v): if not isinstance(v, SpecialEnum): raise ValueError('必须是SpecialEnum子类的实例') return v
验证时只会检查类型归属,不会尝试用空的SpecialEnum基类去实例化值,只要是它的子类实例就会通过验证。
方法二:用Annotated封装可复用的验证逻辑
如果需要在多个模型中复用这个验证规则,可以用Annotated封装验证逻辑:
from pydantic import BaseModel, BeforeValidator from typing import Annotated from enum import Enum class SpecialEnum(Enum): def do_stuff(self): # 自定义业务逻辑 pass class MySpecialEnum(SpecialEnum): A = 1 B = 2 def validate_special_enum_subclass(v): if not isinstance(v, SpecialEnum): raise ValueError('必须是SpecialEnum子类的实例') return v # 封装成可复用的类型 SpecialEnumSubclass = Annotated[SpecialEnum, BeforeValidator(validate_special_enum_subclass)] class MyModel(BaseModel): my_field: SpecialEnumSubclass
方法三:Pydantic v1适配写法
如果仍在使用Pydantic v1,需要替换成validator装饰器:
from pydantic import BaseModel, validator from enum import Enum class SpecialEnum(Enum): def do_stuff(self): # 自定义业务逻辑 pass class MySpecialEnum(SpecialEnum): A = 1 B = 2 class MyModel(BaseModel): my_field: SpecialEnum @validator('my_field') def check_special_enum_subclass(cls, v): if not isinstance(v, SpecialEnum): raise ValueError('必须是SpecialEnum子类的实例') return v
以上方法的核心都是跳过Pydantic默认的枚举验证逻辑(即尝试用基类实例化值),直接检查值的类型是否属于SpecialEnum的子类实例,完美匹配你的需求。
内容的提问来源于stack exchange,提问作者Atai Ambus
相关产品推荐
相关产品推荐

