Fusion
Fusion

Reputation: 5472

Pydantic - Allow missing field

I have a pydantic model. One of its fields must be supplied by user, however, the second one can be present but it is totally okay if it is missing.

In case of missing age, I don't want it to be present on pydantic model instance at all.

My Model:

from pydantic import BaseModel

class Employee(BaseModel):
    name: str
    age: Optional[int]

Problem:

e = Employee(name="Harwey Smith")
e.age  # Has age parameter equal to None, even if not provided.

How do I setup my Employee pydantic model not to have age attribute at all if it is not provided on init? If I would try to access e.nonexistent attribute, AttributeError would be thrown. This is what I want to happen for e.age, if not provided.

Upvotes: 7

Views: 12238

Answers (1)

Hernán Alarcón
Hernán Alarcón

Reputation: 4099

In my opinion, your case is rather unusual and I would always prefer to have a field with a None value. I think it is simpler and receiving an AttributeError is something unexpected if we consider the type hint that any IDE would show for age. Having said that, what you want is possible if you use a @rootvalidator to remove the age field:

from typing import Any, Dict, Optional

from pydantic import BaseModel, root_validator


class Employee(BaseModel):
    name: str
    age: Optional[int]

    @root_validator(skip_on_failure=True)
    def _remove_age_if_none(cls, values: Dict[str, Any]) -> Dict[str, Any]:
        if "age" in values and values["age"] is None:
            del values["age"]
        return values


e = Employee(name="Harwey Smith")
print(e.age)

Output:

AttributeError: 'Employee' object has no attribute 'age'

This approach is something I haven't seen in the Pydantic documentation, but I have seen some answers that show that a @rootvalidator can be used to delete a field. In my opinion this behavior is odd and I would not be surprised if it is changed in future releases of Pydantic. Be careful.

Upvotes: 6

Related Questions