Home > database >  Return Pydantic model as None if all fields are None
Return Pydantic model as None if all fields are None

Time:08-28

Let's say I have a pydantic model with an optional field:

class MyModel(BaseModel):
    field_1: str | None

That I instantiate by passing a dict using parse_obj()

Now, I would like the pydantic object to be None if none of the field members were set.

Example:

data_a = {
    'field_1': 'value_1'
}
obj_a = MyModel.parse_obj(data_a)
print(type(obj_a))  # <class 'MyModel'>
  

data_b = {
    'foo': 'bar'
}
obj_b = MyModel.parse_obj(data_b)
print(type(obj_b))  # I would like this to be NoneType !

Of course I know I could check if the fields exist in the input data before making any instantiation, but I want to avoid that and make it in a more generic way (imagine like having many different models with different fields).

CodePudding user response:

You could use all() and a list comprehension:

if all([val is None for val in dict(obj_b).values()]):
    obj_b = None

Or, alternatively, if none of the fields will purposefully be set to None, you could check if any of the fields have been set:

if not obj_b.__fields_set__:
    obj_b = None

Both of these could be compressed:

# First
obj_b = None if all([val is None for val in dict(obj_b).values()]) else obj_b
# Second
obj_b = obj_b if obj_b.__fields_set__ else None

Here's a base class that does this automatically:

class NoneCheckModel(BaseModel):
    """Model with None checking"""
    @classmethod
    def parse_obj(*args, **kwargs):
        result = super().parse_obj(*args, **kwargs)
        return None if all([val is None for val in dict(result).values()]) else result
  • Related