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

如何让Pydantic模型字段校验枚举名称而非枚举值?

实现Pydantic模型通过枚举名称校验字段

问题场景

我定义了如下枚举类:

class DataType(Enum):
    TIMESTAMP = MyClass("ts")
    DATETIME = MyClass("dt")
    DATE = MyClass("date")

同时定义了包含该枚举类型字段的Pydantic模型:

class Aggregation(BaseModel):
    field_data_type: DataType

希望Pydantic校验字段时匹配枚举的名称而非值,支持通过以下方式实例化模型:

agg = Aggregation(field_data_type="TIMESTAMP")

解决方案

方法1:自定义字段验证器(兼容Pydantic v1/v2)

给模型字段添加前置验证器,将输入的字符串映射到对应的枚举成员:

from pydantic import BaseModel, field_validator
from enum import Enum

class MyClass:
    def __init__(self, value):
        self.value = value

class DataType(Enum):
    TIMESTAMP = MyClass("ts")
    DATETIME = MyClass("dt")
    DATE = MyClass("date")

class Aggregation(BaseModel):
    field_data_type: DataType

    @field_validator('field_data_type', mode='before')
    def parse_enum_name(cls, v):
        if isinstance(v, str):
            try:
                return DataType[v]
            except KeyError:
                raise ValueError(f"无效的DataType名称: {v},可选值为{[e.name for e in DataType]}")
        return v

输入字符串时,验证器会先将其转换为对应的枚举成员,再完成后续校验。

方法2:封装通用枚举字段类型

如果多个模型需要相同逻辑,可以封装成自定义字段,避免重复代码:

from pydantic import GetCoreSchemaHandler
from pydantic_core import core_schema
from enum import Enum

class EnumByNameField:
    @classmethod
    def __get_pydantic_core_schema__(cls, source_type, handler: GetCoreSchemaHandler) -> core_schema.CoreSchema:
        return core_schema.no_info_after_validator_function(
            lambda v: source_type[v] if isinstance(v, str) else v,
            handler(source_type),
        )

# 在模型中使用自定义字段
class Aggregation(BaseModel):
    field_data_type: DataType = EnumByNameField()

方法3:使用Pydantic v2的SmartEnum(推荐)

若使用Pydantic v2,可直接借助SmartEnum实现原生支持,它能自动识别枚举名称或值进行解析:

from pydantic import BaseModel
from pydantic.types import SmartEnum

class MyClass:
    def __init__(self, value):
        self.value = value

class DataType(SmartEnum):
    TIMESTAMP = MyClass("ts")
    DATETIME = MyClass("dt")
    DATE = MyClass("date")

class Aggregation(BaseModel):
    field_data_type: DataType

此时直接用Aggregation(field_data_type="TIMESTAMP")即可正常实例化模型。

内容的提问来源于stack exchange,提问作者Onca

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 14:02:42