Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Validating a nested model in Pydantic

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?

like image 905
Gino Avatar asked Feb 22 '26 02:02

Gino


1 Answers

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)
like image 115
Plagon Avatar answered Feb 23 '26 15:02

Plagon



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!