16
votes

To extend the User object with custom fields, the Django docs recommend using UserProfiles. However, according to this answer to a question about this from a year or so back:

extending django.contrib.auth.models.User also works better now -- ever since the refactoring of Django's inheritance code in the models API.

And articles such as this lay out how to extend the User model with custom fields, together with the advantages (retrieving properties directly from the user object, rather than through the .get_profile()).

So I was wondering whether there is any consensus on this issue, or reasons to use one or the other. Or even what the Django team currently think?

2
Note: the recommendation mentioned in the question is for an outdated version of Django. Refer to the linked question above for guide in new Django versions.user202729

2 Answers

8
votes

I vote for using UserProfiles.

I use several thrid party apps. And a foreign key to a User will always Point to auth.models.User.

Example:

class Article(models.Model):
    user = models.ForeignKey('auth.User') # instead of your CustomUser
    text = ....

And your custom User model:

class CustomUser(User):
    timezone = models.CharField(max_length=50, default='Europe/London')

    # Use UserManager to get the create_user method, etc.
    objects = UserManager()

What will be happen if you access the user field through an Article instance? This will raise an exception:

u = a_article.user
u.timezone

AttributeError: 'User' object has no attribute 'timezone'

Maybe this isn't a problem for you and you wan't to avoid the additional DB query. But i would use the get_profile way.

UPDATE May, 2013

Since Django 1.5 you can extend the default User model, or substitute with a completely customized model.

UPDATE Nov, 2016

The above solution is obsolete, see the comment from wim

2
votes

Here is what James Bennett says in this blog entry about model inheritance:

I’d wager that probably 90% or more of the things people say they want to do with subclasses could be better accomplished by instead defining a related model and linking it back with a unique foreign key.

So I believe the best way to go is still to use an external app, such as some components of Pinax, or the django-profiles app (originally from the same James Bennett).