validation - Pydantic 与枚举子类?

标签 validation inheritance enums subclass pydantic

想象一下我有类似的东西

class SpecialEnum(Enum):
    def do_stuff(self):
         # some cool operation

然后就有了

class MySpecialEnum(SpecialDescriptorEnum):
   A = 1
   B = 2 

然后,我有一个 pydantic 模型:

class MyModel(BaseModel):
    my_field: SpecialEnum

我希望 pydantic 验证 my_field 是 SpecialEnum 子类的某个实例。 然而,pydantic 使用其特殊的枚举验证器,并使用 SpecialEnum(field_value) 进行验证,从而导致始终出现 ValidationError - 因为 SpecialEnum 的目的只是提供功能或界面,而不是值。

有什么解决办法吗?

最佳答案

无需解决方法。您可以通过将特殊的 __get_validators__ 类方法添加到基类 SpecialEnum 来覆盖默认验证。这是一个完整的工作示例:

from __future__ import annotations
from collections.abc import Callable, Iterator
from enum import Enum
from typing import Any

from pydantic import BaseModel


class SpecialEnum(Enum):
    @classmethod
    def __get_validators__(cls) -> Iterator[Callable[..., Any]]:
        yield cls.validate

    @classmethod
    def validate(cls, v: SpecialEnum) -> SpecialEnum:
        if not isinstance(v, cls):
            raise TypeError(f"Must be an instance of `{cls.__name__}`")
        return v

    def do_stuff(self) -> None:
        print("stuff", self)


class MySpecialEnum(SpecialEnum):
    A = 1
    B = 2


class MyModel(BaseModel):
    my_field: SpecialEnum


class Unrelated(Enum):
    foo = "foo"


if __name__ == '__main__':
    instance = MyModel(my_field=MySpecialEnum.A)
    instance.my_field.do_stuff()
    # wrong1 = MyModel(my_field=Unrelated.foo)  # causes a `ValidationError`
    # wrong2 = MyModel(my_field=1)  # ALSO causes a `ValidationError`

不过这里有一个警告。通常,您可以定义一些附加逻辑来接受枚举成员的,甚至允许成员的名称,并让验证器返回相应的枚举成员本身。 (最后一行中的 wrong2 示例。)

但是,由于您的验证方法必须基类 SpecialEnum 上定义,因为这是您用来注释 my_field 的方法,因此无法知道用于检查值/名称的枚举子类。

如果您对此感兴趣,您也许可以为此构造一些额外的逻辑,但我认为只有在确保 SpecialEnum所有子类的所有枚举成员是不同的。

希望这有帮助。

关于validation - Pydantic 与枚举子类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/73919893/

相关文章:

c - Double to enum cast 警告类型混合

ios - Xcode提交到应用商店的问题

java - 用户的业务规则 Java 应用程序

java - 为父类(super class)分配一个引用java

Java枚举匿名内部类和反射

rustdoc 链接到枚举变体

Javascript 单选按钮验证错误弹出不到一秒钟,但不应消失

jquery - 使用 Jquery 验证插件 Ajax 远程验证 WordPress 用户名和电子邮件

C++ list<T>::iterator 不能在派生类模板中使用

c++ - 创建类的过程涉及虚继承