Search code examples
pydanticpydantic-v2

How to get an instance attribute with explicitly specified field names with nested attribute is also an object (Base Model)


I would like to get a list of attributes that have been initialized in obj (Base Model) with nested obj respectively.

I have next code:

from pydantic import BaseModel

class Parameters(BaseModel):
    id: int
    sender_id: int = None

class Options(BaseModel):
    notification: bool = False
    protect: bool = False
    parameters: Parameters = None

opt = Options(protect=True, parameters=Parameters(id=1))
print(opt.model_fields_set)  
# >>> {'protect', 'parameters'}

print(opt.model_dump(include=opt.model_fields_set))  # or
# print(opt.model_dump(include=opt.model_fields_set | {"id"}))
# >>> {'protect': True, 'parameters': {'id': 1, 'sender_id': None}}

i want get only those attributes that I have explicitly specified {'protect': True, 'parameters': {'id': 1}}.

At the moment, I have implemented a function that recursively goes through and collects the necessary attributes

def initialized_fields(cls):
    init_fields = {}
    for field in cls.model_fields_set:
        attr = getattr(cls, field)
        if isinstance(attr, BaseModel):
            init_fields[field] = initialized_fields(attr)
        else:
            init_fields[field] = attr
    return init_fields

please show me how to do it?

Thanks.


Solution

  • You can use exclude_unset option:

    print(opt.model_dump(exclude_unset=True))
    #{'protect': True, 'parameters': {'id': 1}}