Get value of related object by list of fields in @property

Tags: , , ,



I have two model like this with following fields:

Profile: 
    -user(OTO Relation to User)
    -address(OTO to Address)
    -bio
    -gender
    ...
Address: 
    -postal_code
    -phone_number
    -zip_code

I Also I have this list of fields name:

 my_list = ["bio","gender","address.postal_code","address.phone_number", "address.zip_code"]

And finally I want to I create this @property:

@property
def is_complete_profile(self):
    ''' Checks if all the fields have been filled '''
    if self.pk:
        for field_name in my_list:
            value = getattr(self,field_name)
            if not value:
                return False
        return True
    else:
        return False

But for related objects this isn’t the correct way and I got this error:

‘Profile’ object has no attribute ‘address.postal_code’

How Can I use this list for get value of field of Profile objects and related object values?

Notice:

I could solve this problem by using eval function, but because of this and this post, I preferred to throw this solution away.

Answer

Rather than having Profile nose around in its peers’ internals, I would give each class involved an is_complete property (or method) which determines if the instance is complete, and have Profile.is_complete_profile access those properties to determine if the profile is totally complete.

Something like this (untested)

class Address:

    def is_complete(self):
        fields = ["postal_code", "phone_number", "zip_code"]
        for field in fields:
            if not getattr(self, field):
                return False
        return True

class Profile:

    def is_complete(self):
        fields = ["bio","gender"]
        for field in fields:
            if not getattr(self, field):
                return False
        return True

    @property
    def is_complete_profile(self):
        ''' Checks if all the fields have been filled '''
        if self.pk:
            return self.is_complete() and self.address.is_complete()
        return False

This way Profile doesn’t need to change if the names of Address‘s fields change, and only minimal changes are required if additional objects get added to the notion of “completeness”.



Source: stackoverflow