Pydantic 验证模式中未定义的额外字段

mc-*_*ser 29 python validation pydantic

我正在使用 pydantic 进行架构验证,当任何额外字段添加到未定义的架构中时,我想抛出错误。

from typing import Literal, Union

from pydantic import BaseModel, Field, ValidationError


class Cat(BaseModel):
    pet_type: Literal['cat']
    meows: int


class Dog(BaseModel):
    pet_type: Literal['dog']
    barks: float


class Lizard(BaseModel):
    pet_type: Literal['reptile', 'lizard']
    scales: bool


class Model(BaseModel):
    pet: Union[Cat, Dog, Lizard] = Field(..., discriminator='pet_type')
    n: int


print(Model(pet={'pet_type': 'dog', 'barks': 3.14, 'eats': 'biscuit'}, n=1))
""" try:
    Model(pet={'pet_type': 'dog'}, n=1)
except ValidationError as e:
    print(e) """

Run Code Online (Sandbox Code Playgroud)

在上面的代码中,我添加了eats未定义的字段。应用 pydantic 验证并删除我定义的额外值作为响应。我想抛出一个错误eats is not allowed for Dog或类似的东西。有什么办法可以实现这一点吗?

我们是否有机会直接提供输入而不是对象pet
print(Model({'pet_type': 'dog', 'barks': 3.14, 'eats': 'biscuit', n=1}))。我尝试过没有,descriminator但缺少与pet_type. 有人可以指导我如何实现其中之一吗?

Pau*_*l P 52

您可以使用类中的extra字段在模型初始化期间禁止额外的属性(默认情况下,额外的属性将被忽略)。Config

例如:

from pydantic import BaseModel, Extra

class Pet(BaseModel):
    name: str

    class Config:
        extra = Extra.forbid

data = {
    "name": "some name",
    "some_extra_field": "some value",
}

my_pet = Pet.parse_obj(data)   # <- effectively the same as Pet(**pet_data)
Run Code Online (Sandbox Code Playgroud)

将提出VaidationError

ValidationError: 1 validation error for Pet
some_extra_field
  extra fields not permitted (type=value_error.extra)
Run Code Online (Sandbox Code Playgroud)

当模型“嵌套”时也同样有效,例如:

class PetModel(BaseModel):
    my_pet: Pet
    n: int

pet_data = {
    "my_pet": {"name": "Some Name", "invalid_field": "some value"},
    "n": 5,
}

pet_model = PetModel.parse_obj(pet_data)
# Effectively the same as
# pet_model = PetModel(my_pet={"name": "Some Name", "invalid_field": "some value"}, n=5)
Run Code Online (Sandbox Code Playgroud)

将提高:

ValidationError: 1 validation error for PetModel
my_pet -> invalid_field
  extra fields not permitted (type=value_error.extra)
Run Code Online (Sandbox Code Playgroud)

  • 这需要 2023 年更新:配置类不再存在 (5认同)

A. *_*ink 15

首选解决方案是使用ConfigDict(参考文档

from pydantic import BaseModel, ConfigDict

class Pet(BaseModel):
    model_config = ConfigDict(extra='forbid')

    name: str
Run Code Online (Sandbox Code Playgroud)

Paul P 的答案仍然有效(目前),但该类Config已在 pydantic v2.0 中被弃用。另一个已弃用的解决方案是pydantic.Extra.forbid.

上述方法的优点之一是可以进行类型检查。