What is the recommended way to implement multiple user types using Django 1.5’s new configurable user model functionality?
I would like to have two user types: private users and trade users, each with their own set of required fields.
There are two ways I can think to implement this:
1) Multi-table inheritance
class BaseUser(AbstractBaseUser):
email = models.EmailField(max_length=254, unique=True)
# ...
class PrivateUser(BaseUser):
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
# ...
class TradeUser(BaseUser):
company_name = models.CharField(max_length=100)
# ...
Are there any problems with using multi-table inheritance in conjunction with the configurable user model?
2) Using a single model with a “type” attribute
class User(AbstractBaseUser):
email = models.EmailField(max_length=254, unique=True)
user_type = models.CharField(max_length=30, choices={
'P': 'Private',
'T': 'Trade',
})
first_name = models.CharField(max_length=30, blank=True)
last_name = models.CharField(max_length=30, blank=True)
company_name = models.CharField(max_length=100, blank=True)
# ...
This method would require some conditional validation dependent upon user_type.
Which of these methods best suits my use case? Or perhaps there is a better way of achieving this?
Also, In case number 1, how can I filter my users?
Thanks.
Warning: Django 1.5 is very new and the people are still investigating its new features. So my answer is nothing more than my opinion, based on recent research to answer this question.
Both ways are valid ways to achieve the result, with its advantages and disadvantages.
Let’s start with the:
Second option
AbstractBaseUser, as the name says, is an abstract model and does not have a specific tableYou need to check the user_type for any iteration with the model that uses the extra fields:
The resulting SQL would be approximately as follows:
First option
BaseUserManagerfor each child if you want to usecreate_user-like functionsBaseUser.objects.all()*The resulting SQL would be approximately as follows:
* Imagine the following situation:
So, you cannot directly retrieve the subclasses instances by using
BaseUser.objects.all(). There is an excellent blog post by Jeff explaining better how to accomplish “automatic downcast” fromBaseUserto its childs.That said, you should consider the advantages and disadvantages of each approach and their impact on your project. When the involved logic is small (as in the example described), both approaches are valid. But in a more complex scenario, an approach can be better than the other one. I would choose the multi model option because it is more extensible.