Consider this example of a nested model in Pydantic:
from typing import List
from pydantic import BaseModel
from pydantic.class_validators import root_validator
class CarList(BaseModel):
cars: List[str]
colors: List[str]
class CarDealership(BaseModel):
name: str
cars: CarList
@root_validator()
def check_length(cls, v):
cars_list = v.get("cars")
if len(cars_list.cars) != len(cars_list.colors):
raise ValueError("wrong length")
return v
car_deal = {
"cars": {
"cars1": ["toyota", "tesla"],
"colors": ["white", "red"]
}
}
CarDealership.parse_obj(car_deal)
Note that I give the wrong field name to the inner model.
I expected that the outer root validator could only be called if the inner model is valid.
However, I get this error:
File "test.py", line 17, in check_length
if len(cars_list.cars) != len(cars_list.colors):
AttributeError: 'NoneType' object has no attribute 'cars'
I was expecting something like this instead:
pydantic.error_wrappers.ValidationError: 1 validation error for CarList
cars
field required (type=value_error.missing)
How can I make sure the inner model is validated first?
The problem is that the root_validator is called, even if other validators failed before. The idea of pydantic in this case is to collect all errors and not raise an error on first one.
The solution is to set skip_on_failure=True in the root_validator. As a result, the root_validator is only called if the other fields and the submodel are valid.
With this change you will get the following error message:
ValidationError: 2 validation errors for CarDealership
name
field required (type=value_error.missing)
cars -> cars
field required (type=value_error.missing)
If you change the dict to for example the following:
car_deal = {
"name": "Billy",
"cars": {
"cars": ["toyota", "tesla", "vw"],
"colors": ["white", "red"]
}
}
The root_validator is now called and we will receive the expected error:
ValidationError: 1 validation error for CarDealership
__root__
wrong length (type=value_error)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With