views:

6720

answers:

5

What's the best way to extend the User model (bundled with Django's authentication app) with custom fields? I would also possibly like to use the email as the username (for authentication purposes).

I've already seen a few ways to do it, but can't decide on which one is the best.

+17  A: 

There is an official recommendation on storing additional information about users. The Django Book also discusses this problem in section Profiles.

mojo
+16  A: 

The least painful and indeed Django-recommended way of doing this is through a ForeignKey(User) property.

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

I would definitely stay away from changing the actual User class in your Django source tree and/or copying and altering the auth module.

Ryan Duffield
With this solution should you ForeignKey to User or Profile?
superjoe30
+1  A: 

The below one is another approach to extend an User. I feel it is more clear,easy,readable then above two approaches.

http://scottbarnham.com/blog/2008/08/21/extending-the-django-user-model-with-inheritance/

Using above approach:

  1. you don't need to use *user.get_profile().newattribute* to access the additional information related to the user
  2. you can just directly access additional new attributes via user.newattribute
Rama Vadakattu
I like Scott's approach much better, based on the inheritance of the User object rather than directly off the model. Can anyone say if this approach is not wise?
BozoJoe
A: 

Sometimes, this is all you need : http://www.alrond.com/en/2008/may/03/monkey-patching-in-django/

interstar
Terrible approach.
Wahnfrieden
Maybe, but you want to say why? I had to do this, simply because none of the other options worked for me.
interstar
Monkey patching is never a good solution. That's even worse than subclassing the User model. Just use a foreign key relationship. If you couldn't get it working, it's your problem, since this is how everyone else does it (and how Django core developers, and John Bennet, recommend it as well)
Wahnfrieden
That still doesn't answer anything Wahnfrieden.
Mark
It's a bad solution because it breaks the developer's view of Django code. You're adding additional fields to an object that are not defined with the object itself. The next developer who comes along who needs to deal with your fields is going to look at the User model definition **and NOT find them** and then will have to search the codebase to find them. Worse, the Django developers could modify the User model and add new fields with the same name as yours, and then with the next release of Django your code breaks. That's what **terrible approach** means.
Craig Trader
+21  A: 

This is how I do it.

#in models.py
from django.db.models.signals import post_save  

class UserProfile(models.Model):  
    user = models.ForeignKey(User)  
    #other fields here

    def __str__(self):  
          return "%s's profile" % self.user  

def create_user_profile(sender, instance, created, **kwargs):  
    if created:  
       profile, created = UserProfile.objects.get_or_create(user=instance)  

post_save.connect(create_user_profile, sender=User) 

#in settings.py
AUTH_PROFILE_MODULE = 'YOURAPP.UserProfile'

This will create a userprofile each time a user is saved if it is created. You can then use

  user.get_profile().whatever

Here is some more info from the docs

http://docs.djangoproject.com/en/dev/topics/auth/#storing-additional-information-about-users

Raisins
Thanks for the clear example, note that def create_user.... is not part of the UserProfile class and should be aligned left.
With this solution should other models ForeignKey to User or UserProfile?
superjoe30
Other models should use `user = models.ForeignKey( User )`, and retrieve the profile object via `user.get_profile()`. Remember to `from django.contrib.admin.models import User`.
Craig Trader