So you're building a web application, and using the excellent contrib.auth subsystem to manage user accounts. Most probably you need to store additional information about your users, but how? Django profiles to the rescue!
Django provides a lightweight way of defining a profile object linked to a given user. The profile object can differ from project to project, and it can even handle different profiles for different sites served from the same database.
In a nutshell, using Django profiles consists of 3 steps:
- Define a model that holds the profile information.
- Tell Django where to look for the profile object.
- Create the user profile as needed.
Defining the user profile model
The only requirement Django places on this model is that it have a unique ForeignKey to the User model, and is called user. Other than that, you can define any other fields you like.
For our example, we'll create 2 user profile fields (url and company).
account/models.py from django.db import models from django.contrib.auth.models import User class UserProfile(models.Model): user = models.ForeignKey(User, unique=True) url = models.URLField("Website", blank=True) company = models.CharField(max_length=50, blank=True)
Tell Django about the profile object
Accessing a users profile is done by calling user.get_profile(), but in order to use this function, Django needs to know where to look for the profile object.
This is defined in the projects settings.py file.
AUTH_PROFILE_MODULE = "account.UserProfile"
Important note: The settings value is appname.modelname, and not appname.models.modelname as you might expect. The reason for this is that Django is not doing a direct import, but using an internal model-loading function.
Once defined, and if the profile exists, accessing a users profile is simple.
foo/views.py @login_required def view_foo(request): user_profile = request.user.get_profile() url = user_profile.url #OR url = request.user.get_profile().url
Create the user profile as needed
Notice in the section above I mentioned "if the profile exists". This is because the get_profile() function will raise a DoesNotExist exception if the profile does not exist.
One of the common solutions to this issue is to create the profile when a user is registered using a signal (see my post on Django Signals).
Another option is catch the exception, and redirect the user to a profile creation form. You usually want to do this if the profile fields are mandatory.
My personal favorite though, is to have the profile created automatically when referenced, with the added bonus of being able to reference a users profile as user.profile instead of user.get_profile()
account/models.py ... class UserProfile(models.Model): user = models.ForeignKey(User, unique=True) ... User.profile = property(lambda u: UserProfile.objects.get_or_create(user=u))
To reiterate, including the above enables us to reference the users profile with cleaner code, and have it created if it does not exist.
foo/views.py @login_required def view_foo(request): url = request.user.profile.url
Ever needed to store additional user information? Post a comment!