Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - Multiple User Profiles

Initially, I started my UserProfile like this:

from django.db import models from django.contrib.auth.models import User  class UserProfile(models.Model):     user = models.OneToOneField(User)     verified = models.BooleanField()     mobile = models.CharField(max_length=32)      def __unicode__(self):         return self.user.email 

Which works nicely along with AUTH_PROFILE_MODULE = 'accounts.UserProfile' set in settings.py.

However, I have two different kinds of users in my website, Individuals and Corporate, each having their own unique attributes. For instance, I would want my Individual users to have a single user only, hence having user = models.OneToOneField(User), and for Corporate I would want them to have multiple users related to the same profile, so I would have user = models.ForeignKey(User) instead.

So I thought about segregating the model into two different models, IndivProfile and CorpProfile, both inheriting from UserProfile while moving the model-specific attributes into the relevant sub-models. Seems like a good idea to me and would probably work, however I would not be able to specify AUTH_PROFILE_MODULE this way since I'm having two user profiles that would be different for different users.

I also thought about doing it the other way around, having UserProfile inherit from multiple classes (models), something like this:

class UserProfile(IndivProfile, CorpProfile):     # some field      def __unicode__(self):         return self.user.email 

This way I would set AUTH_PROFILE_MODULE = 'accounts.UserProfile' and solve its problem. But that doesn't look like it's going to work, since inheritance in python works from left to right and all the variables in IndivProfile will be dominant.

Sure I can always have one single model with IndivProfile and CorpProfile variables all mixed in together and then I would use the required ones where necessary. But that is just doesn't look clean to me, I would rather have them segregated and use the appropriate model in the appropriate place.

Any suggestions of a clean way of doing this?

like image 854
Aziz Alfoudari Avatar asked Mar 10 '12 20:03

Aziz Alfoudari


People also ask

Can django handle multiple users?

No matter what strategy you pick, or what is your business model, always use one, and only one Django model to handle the authentication. You can still have multiple user types, but generally speaking it's a bad idea to store authentication information across multiple models/tables.

Can I have two user models in django?

You can have in your models two user classes that extend from the USER model.


2 Answers

You can do this in following way. Have a profile which will contains common fields which are necessary in both profiles. And you have already done this by creating class UserProfile.

class UserProfile(models.Model):     user = models.ForeignKey(User)     # Some common fields here, which are shared among both corporate and individual profiles  class CorporateUser(models.Model):     profile = models.ForeignKey(UserProfile)     # Corporate fields here      class Meta:         db_table = 'corporate_user'  class IndividualUser(models.Model):     profile = models.ForeignKey(UserProfile)     # Individual user fields here     class Meta:         db_table = 'individual_user' 

There is no rocket science involved here. Just have a keyword which will distinguish between corporate profile or individual profile. E.g. Consider that the user is signing up. Then have a field on form which will differentiate whether the user is signing up for corporate or not. And Use that keyword(request parameter) to save the user in respective model.

Then later on when ever you want to check that the profile of user is corporate or individual you can check it by writing a small function.

def is_corporate_profile(profile):     try:         profile.corporate_user         return True     except CorporateUser.DoesNotExist:         return False  # If there is no corporate profile is associated with main profile then it will raise `DoesNotExist` exception and it means its individual profile # You can use this function as a template function also to use in template {% if profile|is_corporate_profile %} 

Hope this will lead you some where. Thanks!

like image 156
Aamir Rind Avatar answered Sep 30 '22 04:09

Aamir Rind


I have done it this way.

PROFILE_TYPES = (     (u'INDV', 'Individual'),     (u'CORP', 'Corporate'), )  # used just to define the relation between User and Profile class UserProfile(models.Model):     user = models.ForeignKey(User)     profile = models.ForeignKey('Profile')     type = models.CharField(choices=PROFILE_TYPES, max_length=16)  # common fields reside here class Profile(models.Model):     verified = models.BooleanField(default=False) 

I ended up using an intermediate table to reflect the relation between two abstract models, User which is already defined in Django, and my Profile model. In case of having attributes that are not common, I will create a new model and relate it to Profile.

like image 43
Aziz Alfoudari Avatar answered Sep 30 '22 05:09

Aziz Alfoudari