Reputation: 2094
Why does pydantic not validate an argument that is the list of Foo objects but throws ValidationError when the argument is a list of primitive types?
Can I enforce the validation of complex types?
Validation doesn't work:
from typing import List
from pydantic import BaseModel
class Foo(BaseModel):
kind: str = "foo"
class Bar(BaseModel):
kind: str = "bar"
class Spam(BaseModel):
foos: List[Foo]
spam = Spam(foos=[Bar()])
print(spam.dict())
>>> {'foos': [{'kind': 'bar'}]}
Validation works:
class Spam(BaseModel):
foos: List[int]
spam = Spam(foos=[Bar()])
print(spam.dict())
pydantic.error_wrappers.ValidationError: 1 validation error for Spam
foos -> 0
value is not a valid integer (type=type_error.integer)
Upvotes: 2
Views: 11433
Reputation: 32163
When working with pydantic
, it should be remembered that:
pydantic is primarily a parsing library, not a validation library. Validation is a means to an end: building a model which conforms to the types and constraints provided.
In other words, pydantic guarantees the types and constraints of the output model, not the input data.
For additional validation of incoming data, a tool is provided - validators. For example:
class Spam(BaseModel):
foos: List[Foo]
@validator('foos', pre=True, each_item=True)
def check_squares(cls, v):
assert isinstance(v, Foo), "Foo is only allowed"
return v
Upvotes: 5
Reputation: 556
You can't validate the value like kind: str = "foo"
. You have to use Field in order to validate values of a variable.
Try:
from typing import List
import pydantic
from pydantic import BaseModel, Field
class Foo(BaseModel):
kind: str = Field(const="foo", default="foo")
class Bar(BaseModel):
kind: str = Field(const="bar", default="bar")
class Spam(BaseModel):
foos: List[Foo]
try:
Spam.parse_obj({'foos': [{'kind': 'bar'}]})
except pydantic.ValidationError as e:
print(e)
Upvotes: 0