4

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.

Fusion
  • 5,046
  • 5
  • 42
  • 51
  • I cannot reproduce your error. The validation does not fail and an `Employee` can be created successfully with Pydantic 1.9.1. – Hernán Alarcón Jul 16 '22 at 01:39
  • @HernánAlarcón Sorry, I just edited question to be more understandable. My fault. – Fusion Jul 16 '22 at 10:04
  • In pydantic V2 you'll be able to use a TypedDict which supports this functionality. It's not possible pydantic v1.x – SColvin Aug 03 '22 at 15:23

1 Answers1

4

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.

Hernán Alarcón
  • 3,494
  • 14
  • 16