Pydantic未应用默认值

1 投票
2 回答
71 浏览
提问于 2025-04-14 16:12

我有一个这样的数据结构。如果我在'location'里输入“启用”或“禁用”,那么这个功能就能正常工作,验证也没问题。如果我输入一个随机字符串,它就会失败(这也是应该的)。问题是,如果'location'是一个空字符串,这个验证也会失败。我希望它能设置一个默认值,并且通过验证。我尝试添加下面的验证函数,但根本没有进入这个函数。它自动就失败了。

Input should be 'disabled' or 'enabled' [type=literal_error, input_value='', input_type=str]" 

我已经添加了默认值,但它还是失败了。你觉得我漏掉了什么吗?

from pydantic import BaseModel, Field, validator
from typing_extensions import Annotated, Literal

ENABLED_DISABLED = Literal["disabled", "enabled"]


class GlobalSchema(BaseModel):
    location: Annotated[ENABLED_DISABLED, Field(description="Location")] = "disabled"

    # @validator('location')
    # def validate_location(cls, value):
    #     if value not in ENABLED_DISABLED:
    #         raise ValueError(f'Invalid value for location. Must be one of: {", ".join(ENABLED_DISABLED)}')
    #     return value or "disabled"

2 个回答

1

为了让你能够传递任何值,你应该把 ENABLED_DISABLED 替换成 str。你之所以无法调试,是因为你需要像这样传递位置的值:a = GlobalSchema(location="")。这是因为当你没有指定确切的字段时,验证函数会返回一个额外的值。最后,当值不在你预定义的列表中时,你不应该抛出异常。所以你可以得到类似这样的代码:

from pydantic import BaseModel, Field, field_validator
from typing_extensions import Annotated, Literal

ENABLED_DISABLED = Literal["disabled", "enabled"]


class GlobalSchema(BaseModel):
    location: Annotated[str, Field(description="Location")] = "disabled"

    @field_validator('location')
    def validate_location(cls, value):
        return "enabled" if value == "enabled" else "disabled"


print(GlobalSchema(location=""))
1

我觉得可以通过使用一个 prebefore 验证器来实现想要的效果。这个验证器会在 Pydantic 进行内部验证之前被调用,所以不需要重新实现对字面值的验证。我的建议解决方案大概是这样的:

from pydantic import BaseModel, Field, field_validator
from typing_extensions import Annotated, Literal

ENABLED_DISABLED = Literal["disabled", "enabled"]


class GlobalSchema(BaseModel):
    location: Annotated[ENABLED_DISABLED, Field(description="Location")] = "disabled"

    @field_validator("location", mode="before")
    def validate_location(cls, value):
        if value == "":
            return cls.model_fields["location"].default
        
        return value

print(GlobalSchema(location=""))

这段代码会输出:

location='disabled'

如果值不正确,它会抛出:

ValidationError: 1 validation error for GlobalSchema
location
  Input should be 'disabled' or 'enabled' [type=literal_error, input_value='foo', input_type=str]
    For further information visit https://errors.pydantic.dev/2.5/v/literal_error

我建议你再看看 Pydantic 文档中的验证器部分: https://docs.pydantic.dev/latest/concepts/validators/

希望这对你有帮助!

撰写回答