The title is a little rough so let me explain it with more details:
I have a table called Identity
which is a simple table like that:
class Identity(models.model):
identity_name = models.CharField(max_length=20, db_index=True) # name of the ID
service_name = models.CharField(max_length=50)
An example row in the database would be a Facebook identity with identity_name='FacebookID'
and a service_name='Facebook'
.
Now, to link that to a user, I have the following table:
class UserIdentity(models.Model):
user = models.ForeignKey('django.contrib.auth.models.User', db_index=True)
identity_type = models.ForeignKey('Identity', db_index=True)
value = models.CharField(maxlength=50) # the ID value
objects = models.Manager()
identities = IdentitesManager()
Let say Bob
is a instance of the django.contrib.auth.models.User
. I would like to access its Facebook identity with Bob.identities.facebook
where facebook
is dynamically generated in the IdentitiesManager
.
Now you know the context, here is the question: how do I retrieve from the database the identities, to use them in the IdentitiesManager
?
Thanks for reading.
Finally, I found how to do that. I created a class inheriting from dict
and made it create its attributes (with setattr
) based on the data contained in the dict. The class code is :
class IdentityDictionary(dict):
"""
Create a custom dict with the identities of a user.
Identities are accessible via attributes or as normal dict's key/value.
"""
def __init__(self, user, key='service_name'):
identities = UserIdentity.objects.filter(user=user)
dict_identities = dict([ (getattr(user_id.identity, key).replace(' ', '').lower(), user_id.identity) for user_id in identities ])
super(IdentityDictionary, self).__init__(dict_identities)
for id_name, id_value in dict_identities.items():
setattr(self, id_name, id_value)
Then I made a mixin to add to the user class:
class IdentitiesMixin(object):
"""
Mixin added to the user to retrieve identities
"""
_identities_dict = {}
_is_identities_initialized = False
@property
def identities(self):
if not self._is_identities_initialized :
self._identities_dict = IdentityDictionary(self)
self._is_identities_initialized = True
return self._identities_dict
One more point: the custom dict is not intended for reusability : attributes are not updated if the dict
is (hopefully, it is not a problem with the class use cases).