The User-Profile Pattern in Django

Denver Web Developer Gavin Wahl Posted by Gavin Wahl on March 17, 2013
Denver computer programming, Denver Web Development, Django 1.5

With the release of Django 1.5, you can now replace the django.contrib.auth User model with your own customized version. This allows you to alter the database fields of the User to, for example, use an email address as a username. It would seem that this obviates the need for the user profile pattern. This is not the case. The User model should only be responsible for authentication and authorization, not storing extra data. When an app needs to store data related to a User, the app should use its own model and define a OneToOneField to the AUTH_USER_MODEL.

This is different from Django's pre-1.5 implementation of the user profile pattern. Django's implementation was ugly and unnecessary, which turned many programmers off of the pattern in general. With Django's reverse relationships, explicit support for user profiles is not necessary. user.get_profile() can just be user.userprofile. Additionally, a single user profile shouldn't be special. Every app that needs profile data should bring their own.

Single responsibility principle

Every class should have a single responsibility. The only responsibility of the User class is to perform authentication and authorization. The storage or manipulation of information not related to authentication or authorization in the User model is a violation of this principle.

Reusability

The best Django apps are reusable. When an app requires extra user data, it should be implemented in a way that can be reused elsewhere. A user profile is eminently reusable, because it exists in isolation. Consider adding a 'phone number' field to a user. If the data is stored on the User model itself, installing an app requires editing the site's user model. A profile, on the other hand, can be installed with no modifications.

Isolation

The data from different apps should be isolated and independent from other apps. Modifying a single User model to store every installed app's data does not allow for reuse. If every app's profile is separate, they can be installed and modified without any changes to the User model and in isolation from other apps. Manually modifying code is not only a violation of the open-closed principle, but is dangerous when dealing with important authentication code. It is too easy to make security mistakes when haphazardly modifying the User class.

Explicit dependencies

An app-specific user profile makes data dependencies explicit. If an app provides a profile, it knows it can rely on the profile's data. Otherwise, the app should not make any assumptions on the available data beyond what is mandated by the User class contract.

Example

class ContactInfo(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL)
    phone_numer = models.CharField()
    address = models.CharField()

def get_contact_info(user):
    return user.contactinfo

Or, for complete isolation when worried about clashing related_names on User, don't use a related name:

class ContactInfo(models.Model):
    user = models.OneToOneField(settings.AUTH_USER_MODEL,
                                related_name='+')

def get_contact_info(user):
    return ContactInfo.objects.get(user=user)

tl;dr

Despite the ability to replace the User model, the role of the user profile is still important. The pattern encourages reusability, isolation, and beneficial factoring. The User model should only be replaced when absolutely necessary to customize the authentication or authorization that Django provides.

Posted in: Programming

2 responses to "The User-Profile Pattern in Django"

Miguel M. Almeida (12/29/2013 @ 7:45am)

Many thanks for this article ;) It saved me a lot of hours to learn this by myself.

Deepak Malik (10/19/2013 @ 3:15pm)

Thanks for wonder explanation. I'm about to integrate on eCommerce site.

Leave a Comment

Name: *

Email: *

URL:

Message: *

CONTACT US Got a comment? Want a quote?
Email or call 303.952.7490

Denver Web Design | Search Blog

Search Blog

Denver Web Design and Development | Blog Archives

Archive

Denver Interactive Agency | Blog Categories

Categories

Denver Website Design | Blog Tags

Tags

Ad Extensions AdWords agile agile marketing awards B2B Internet Marketing Binary Blogging Branding careers content development conversion optimization database denver advertising agency Denver computer programming Denver Interactive Agencies Denver Interactive Agency Denver Internet Marketing Denver Internet Marketing advice denver non profit marketing denver ppc denver ppc advertising denver programming denver programming jobs Denver search engine marketing Denver Search Engine Optimization Denver SEO denver seo agency Denver SEO intern denver social media Denver social media marketing Denver Software Development Denver Usability Denver usability consulting Denver web design Denver web designer Denver Web Development denver web sites Denver website design denver website development Django 1.5 facebook Favorite Restaurants Fusionbox Fusionbox food Fusionbox Framework google grants Google rankings HTML pages information architecture Internet Marketing JavaScript jobs keyword research KidsTek link building linkbuilding mobile web applications Non Profit Marketing online reputation management Pay per Click PDF pages PHP development post launch checklist PPC pre launch checklist Programming Project Management pubcon Python jobs reputation management Restaurant week 2013 Ruby jobs search engine optimization SEO SEO advice seo-friendly urls social media advice Social Media Marketing Social Media Marketing for Credit Unions social media sharing SQL stock photos TextMate Top B2B Interactive Agencies web design web designer in Denver Web Development web development jobs WORM