如何在Python Pydantic BaseModel中要求预定义的字符串值?

46

在pydantic中有内置的方法可以指定选项吗?例如,假设我想要一个字符串值,它必须是“foo”或“bar”中的一个。

我知道我可以使用正则表达式验证来实现此目的,但由于我与FastAPI一起使用pydantic,用户只会将所需输入视为字符串,但当他们输入某些内容时,它会产生验证错误。所有pydantic的内置验证都显示在api界面中,因此如果有类似以下的东西就太好了:

class Input(BaseModel):
     option: "foo" || "bar"
3个回答

101

是的,您可以使用枚举:

class Choices(Enum):
    foo = 'foo'
    bar = 'bar'

class Input(BaseModel):
     option: Choices

点击此处查看。

或者您可以使用Literal

class Input(BaseModel):
     option: Literal['foo', 'bar']

点击这里


7
谢谢,这很有效。我还想补充一点,在Python 3.8+中,使用from typing import Literal,而在<3.8的版本中则需要使用from typing_extensions import Literal - Gabriel Petersson
19
为了简单起见,你可以使用 from pydantic.typing import Literal,它适用于两种情况。 - SColvin

3

想在这里添加另一个选项。你也可以使用正则表达式。对我来说更好用,因为Literal直到Python 3.8才可用(这对我来说不是一个容易的升级),并且由于我只期望每个字符串只有一个,所以枚举并不真正适合。

class YourClass(pydantic.BaseModel):
  your_attribute: pydantic.constr(regex="^yourvalwith\.escapes\/abcd$")

1
最简单的方法:使用typing.Literal 当您可以硬编码您的值时,Literal是一个不错的选择。
class Input(BaseModel):
    option: Litera["foo", "bar"]

如果你的字符串列表是动态的,它将会失败。
allowed_values = ["foo", "bar"]

class Input(BaseModel):
    option: Literal[allowed_values]

备选方案:使用验证器

假设无法将其转码为正则表达式(比如说你有对象,而不仅仅是字符串),那么你可以使用字段验证器:

allowed_values = ["foo", "bar"]

class Input(BaseModel):
    option: str

    @field_validator("option")
    def validate_option(cls, v):
        assert v in allowed_values
        return v

最佳:带有注释验证器的可重用字段

假设这个字段(和验证器)将在您的代码库中被重复使用。更好的方法是创建一个带有注释验证器的“自定义字段类型”,如下所示:

from typing import Annotated
from pydantic import BaseModel, AfterValidator


allowed_values = ["foo", "bar"]

def option_in_allowed_values(v):
    """Ensures option is allowed"""
    assert v in allowed_values
    return v

custom_option = Annotated[str, AfterValidator(option_in_allowed_values)]


class Input(BaseModel):
    option: custom_option


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接