模式中未定义的额外字段的 Pydantic 验证
Pydantic validations for extra fields that not defined in schema
我正在使用 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) """
在上面的代码中,我添加了未定义的 eats
字段。应用了 pydantic 验证,并删除了我定义的额外值作为响应。我想抛出一个错误,说 eats is not allowed for Dog
或类似的东西。有什么办法可以实现吗?
我们是否可以直接提供输入而不是 pet
对象?
print(Model({'pet_type': 'dog', 'barks': 3.14, 'eats': 'biscuit', n=1}))
。我在没有 descriminator
的情况下尝试过,但是缺少与 pet_type
相关的那些特定验证。有人可以指导我如何实现其中之一吗?
Pydantic 用于使用模式验证您的输入。在您的情况下,您想删除其中一项验证功能。
我认为您应该创建一个继承自 BaseModel
的新 class
class ModifiedBaseModel(BaseModel):
def __init__(__pydantic_self__, **data: Any) -> None:
registered, not_registered = __pydantic_self__.filter_data(data)
super().__init__(**registered)
for k, v in not_registered.items():
__pydantic_self__.__dict__[k] = v
@classmethod
def filter_data(cls, data):
registered_attr = {}
not_registered_attr = {}
annots = cls.__annotations__
for k, v in data.items():
if k in annots:
registered_attr[k] = v
else:
not_registered_attr[k] = v
return registered_attr, not_registered_attr
然后创建验证 classes
class Cat(ModifiedBaseModel):
pet_type: Literal['cat']
meows: int
现在您可以创建一个新的 Cat
而不必担心未定义的属性。像这样
my_cat = Cat(pet_type='cat', meows=3, name='blacky', age=3)
第二个问题,要直接从 dict
输入,你可以使用双星号 **
Dog(**my_dog_data_in_dict)
或
Dog(**{'pet_type': 'dog', 'barks': 3.14, 'eats': 'biscuit', n=1})
你可以在模型初始化时使用Config
extra
fieldclass到forbid额外的属性(默认情况下,额外的属性会被忽略)。
例如:
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)
会提出 VaidationError
:
ValidationError: 1 validation error for Pet
some_extra_field
extra fields not permitted (type=value_error.extra)
当模型“嵌套”时也适用,例如:
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)
将提高:
ValidationError: 1 validation error for PetModel
my_pet -> invalid_field
extra fields not permitted (type=value_error.extra)
我正在使用 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) """
在上面的代码中,我添加了未定义的 eats
字段。应用了 pydantic 验证,并删除了我定义的额外值作为响应。我想抛出一个错误,说 eats is not allowed for Dog
或类似的东西。有什么办法可以实现吗?
我们是否可以直接提供输入而不是 pet
对象?
print(Model({'pet_type': 'dog', 'barks': 3.14, 'eats': 'biscuit', n=1}))
。我在没有 descriminator
的情况下尝试过,但是缺少与 pet_type
相关的那些特定验证。有人可以指导我如何实现其中之一吗?
Pydantic 用于使用模式验证您的输入。在您的情况下,您想删除其中一项验证功能。
我认为您应该创建一个继承自 BaseModel
class ModifiedBaseModel(BaseModel):
def __init__(__pydantic_self__, **data: Any) -> None:
registered, not_registered = __pydantic_self__.filter_data(data)
super().__init__(**registered)
for k, v in not_registered.items():
__pydantic_self__.__dict__[k] = v
@classmethod
def filter_data(cls, data):
registered_attr = {}
not_registered_attr = {}
annots = cls.__annotations__
for k, v in data.items():
if k in annots:
registered_attr[k] = v
else:
not_registered_attr[k] = v
return registered_attr, not_registered_attr
然后创建验证 classes
class Cat(ModifiedBaseModel):
pet_type: Literal['cat']
meows: int
现在您可以创建一个新的 Cat
而不必担心未定义的属性。像这样
my_cat = Cat(pet_type='cat', meows=3, name='blacky', age=3)
第二个问题,要直接从 dict
输入,你可以使用双星号 **
Dog(**my_dog_data_in_dict)
或
Dog(**{'pet_type': 'dog', 'barks': 3.14, 'eats': 'biscuit', n=1})
你可以在模型初始化时使用Config
extra
fieldclass到forbid额外的属性(默认情况下,额外的属性会被忽略)。
例如:
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)
会提出 VaidationError
:
ValidationError: 1 validation error for Pet
some_extra_field
extra fields not permitted (type=value_error.extra)
当模型“嵌套”时也适用,例如:
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)
将提高:
ValidationError: 1 validation error for PetModel
my_pet -> invalid_field
extra fields not permitted (type=value_error.extra)