Django Registration for Newbies
introduction
This is another in a series of posts exploring how to build social networking capabilities in a Django application while also exploring related tools and approaches that are new to me. I have been sidetracked for some time now with discussions of REST, and if you’ve been following this series, you’re probably pretty sick of that topic by now. So, lets get back to the application itself.
I recently turned my attention to user account management in Django and what follows are (cleaned-up) notes I made while exploring the django-registration contribution. As a result, this post is very introductory and task oriented, but hopefully, it will help orient newcomers like me to what’s available and provide a foundation for exploring these topics in more depth.
Most sites you build in Django will probably require users to self-register, authenticate and manage their own accounts, and this is certainly a basic requirement of social networking sites. Like any mature Web framework, Django provides robust user management and authentication functionality that, along with some robust add-on code, will allow you to quickly implement common user registration, authentication, and account management approaches while also allowing you to easily customize those approaches for your application’s needs.
Although this post is part of a series, I will try to keep the discussion general, so it shouldn’t assume any knowledge of previous posts.
quickly implementing user registration
Once you’re familiar with Django and the basic documentation on the project’s site, you could do much worse than to look through the posts on James Bennett’s blog, The B-List, which contains many deep insights into Django. One such insightful post, user registration shows how to build a typical registration process in Django. James eventually implemented a newer, more robust version of his approach as a contribution, django-registration, that can easily be installed and used generically in your own application.
The django-registration contribution serves a narrowly defined purpose; from the user’s perspective, it provides two primary functions: account registration and account activation, including the following validations:
- usernames are checked to ensure uniqueness
- passwords must be entered twice and match
- users are asked to accept terms of service
There are two minor prerequisites to using django-registration: you need to use a fairly current version of Django, 0.95 and above that includes the newforms library. If you regularly update Django from Subversion, you should already be running a compatible version. For the default templates to work correctly, you will also need to ensure that django.contrib.humanize is included in your INSTALLED_APPS directive in settings.py, so that it might look like this:
INSTALLED_APPS = (
'django.contrib.auth',
'django.contrib.humanize',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.admin',
)
The humanize application is part of the Django distribution, like the auth application, and adding it to INSTALLED_APPS is the only step necessary to activate it–you don’t even have to run syncdb. Humanize is a nice application for adding polish to your interface as it massages certain types of numbers into more user friendly formats, such as adding commas to large integers for example.
You will also need the auth, sessions and sites applications indicated above, as well as the SessionMiddleware and AuthenticationMiddleware entries in MIDDLEWARE_CLASSES in settings.py, all of which should already be included in your settings.py by default if you started your application using the django-admin.py startproject command. I also recommend including the admin application in INSTALLED_APPS if you already haven’t, for reasons that will become clear later. Finally, django-registration will need access to an SMTP server to send emails (or you could follow this recipe to use GMail instead).
Complete and up-to-date documentation is provided with the django-registration distribution, but I’m going to try to make the processes of installing and customizing this contribution more explicit for newcomers like me who are still learning their way around Django. Like humanize, django-registration is also a normal Django application, so, for example, it will get checked-out of Subversion and placed alongside any applications in your Django project directory, in a sub-directory called ‘registration’. So, for my ‘tagging_exploration’ django project, I would do this to add the ‘registration’ application at the same level as my ‘tagging’ application:
> cd tagging_exploration
> svn checkout http://django-registration.googlecode.com/svn/trunk/ registration
To activate and configure django-registration, first add it to your INSTALLED_APPS directive in settings.py:
INSTALLED_APPS = (
'registration',
'tagging',
'django.contrib.auth',
'django.contrib.humanize',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.sites',
'django.contrib.admin',
)
Then from your Django project directory, install its RegistrationProfile model in the customary way:
> python manage.py syncdb
A few remaining entries in settings.py are needed to control the behavior of django-registration:
ACCOUNT_ACTIVATION_DAYS=7
EMAIL_HOST='localhost'
EMAIL_PORT=1023
EMAIL_HOST_USER='username'
EMAIL_HOST_PASSWORD='password'
Of course, you will have to customize these settings for your environment. ACCOUNT_ACTIVATION_DAYS is an integer representing the number of days in which a user can successfully activate their account.
The django-registration application also sends out emails that contain your site’s URL for the activation link, and that URL is dynamically determined using the ’sites’ contributed application indicated above. By default, your domain name is listed as ‘example.com’, and the easiest way to change this is to log into the admin application and click on the ‘Sites’ link on the admin home page to get to the relevant entry.
Then, include django-registration’s urls in your project’s urls.py, which for a new project might look like this:
urlpatterns = patterns('',
(r'^admin/', include('django.contrib.admin.urls')),
(r'^accounts/', include('registration.urls')),
)
The only thing left to do now is to specify the templates that will be used. You could point to the actual django-registration templates directly by editing the TEMPLATE_DIRS setting in settings.py. For example, this is how I would do it in my project, which has my toy application called ‘tagging’, and uses a little Python trickery to dynamically determine the absolute location of the template directories:
import os
dirname = os.path.dirname(globals()["__file__"])
TEMPLATE_DIRS = (
os.path.join(dirname, 'tagging/templates'),
os.path.join(dirname, '../registration/templates'),
)
But ultimately, you will probably want to customize these templates and do so on a per-application basis. So, instead of adding an entry to TEMPLATE_DIRS, copy the registration/templates directory from the django-registration templates directory (that’s registration/templates to be exact) to your application’s templates directory so that in my tagging application, I would have the following template directories off the ‘tagging’ application root:
templates/registration
templates/tagging
Out of the box, the django-registration templates inherit from the base.html template–the template that contains the basic structure of your application’s interface–and override the following blocks:
- title
- sidebar
- content_header
- content
- main_content
If you’re starting a new application, you may want to create a very simple base.html template directly under your application’s templates directory to get the basic django-registration templates working so they can then be customized more naturally. Here is a minimal template to get you started:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<style>
input.required, error {
border: 2px solid red;
}
</style>
<title>{% block title %}Tagging Exploration{% endblock %}</title>
</head>
<body>
<div id="sidebar">
{% block sidebar %}{% endblock %}
</div>
<div id="content">
{% block content %}{% endblock %}
{% block main_content %}{% endblock %}
</div>
</body>
</html>
In this bare-bones template, I did add a CSS style to demonstrate that every django-registration form field that is required also has a ‘required’ CSS class defined for it, that you can style accordingly for your site. This CSS class is actually defined in the newforms code in django-registration’s forms.py module.
Conclusion
At this point, django-registration should be properly installed and configured, and you should be able to begin integrating it into your application.
The django-registration application works with Django’s standard user authentication system. So for example, when a user activates an account, the is_active field of the Users object gets updated, indicating the user is allowed to login.
The django-registration application also uses the authentication application’s generic views for login and logout. Other generic views provided by the authentication application that you will likely want to use include those for changing passwords and resetting forgotten passwords. Following the approach taken by the django-registration contribution, we can add these to urls.py, so that the full urls.py now looks something like this:
from django.conf.urls.defaults import *
from django.contrib.auth.views import password_reset, password_reset_done, password_change, password_change_done
from django.views.generic.simple import direct_to_template
urlpatterns = patterns('',
(r'^admin/', include('django.contrib.admin.urls')),
(r'^accounts/', include('registration.urls')),
)
urlpatterns += patterns('',
(r'^accounts/profile/$', direct_to_template, {'template': 'registration/profile.html'}),
(r'^accounts/password_reset/$', password_reset, {'template_name': 'registration/password_reset.html'}),
(r'^accounts/password_reset_done/$', password_reset_done, {'template_name': 'registration/password_reset_done.html'}),
(r'^accounts/password_change/$', password_change, {'template_name': 'registration/password_change.html'}),
(r'^accounts/password_change_done/$', password_change_done, {'template_name': 'registration/password_change_done.html'}),
)
These views in turn expect to find the following templates, respectively:
- templates/registration/profile.html
- templates/registration/password_reset.html
- templates/registration/password_reset_done.html
- templates/registration/password_change_done.html
- templates/registration/password_change_done.html
And the password reset view also expects a template at templates/registration/password_reset_email.html to know how to format the email sent out. (I’ll explain the significance of the profile template momentarily.)
Then, to protect views that require authentication, you can use the login_required decorator as described in the following example from the djangoproject.com user authentication documentation:
from django.contrib.auth.decorators import login_required
@login_required
def my_view(request):
# pass
This allows the view to be executed normally when the user is logged in, or otherwise automatically redirect to accounts/login, assigning the appropriate absolute URL to the ‘next’ variable as a string and passing it to the login view. (By default, the ‘next’ variable is set to go to accounts/profile in the login view, which I added to urls.py above using the direct_to_template generic view.) You can also access this functionality directly through the redirect_to_login view of the authentication application. Data and methods associated with a logged in user can then be accessed within both view and template code; refer to the User authentication in Django documentation to see what is available.
Hopefully this introduction to django-registration will help you quickly implement this important functionality in your application and orient you to how Django itself manages user accounts and authentication. The django-registration project Web site also has information that can help you troubleshoot specific issues you may experience, and also describes how to clean up user accounts that have not been activated in the allowed time.
In the unlikely event that django-registration can’t be configured to provide the functionality you need, you may want to consult the Django book which describes how to write your own registration process.
resources
- source code used in this post
- Extending the User model on The B-List.
- User Registration on The B-List.
- django-registration contribution Home Page
- django.contrib.humanize Documentation
- Django | Documentation | The newforms library
- Django | Documentation | Generic Views
- Django | Documentation | User authentication in Django
- The Django Book, Chapter 12: Sessions, users, and registration
- Use email addresses for user name on djangosnippets.com
- Django registration with GMail account on djangosnippets.com
previous posts in this series

After you add registration to INSTALL_APPS list , app_directories template loader will automaticly look directory registration/templates for template file.
Doh! Thanks for catching that…
[...] stone mind » Django Registration for Newbies — A nice tutorial for implementing user-driven account registration to Django. Django has a lot of great facilities to make this happen, but you just need to tie them all together for your specific needs. [...]
I am trying to install django-registration I have checked it out into /project/registration/ but when I add it to /project/settings.py. I get a few errors:
File “manage.py”, line 11, in ?
execute_manager(settings)
File “/home/fksource/django/django_src/django/core/management.py”, line 1736, in execute_manager
execute_from_command_line(action_mapping, argv)
File “/home/fksource/django/django_src/django/core/management.py”, line 1626, in execute_from_command_line
translation.activate(’en-us’)
File “/home/fksource/django/django_src/django/utils/translation/__init__.py”, line 66, in activate
return real_activate(language)
File “/home/fksource/django/django_src/django/utils/translation/__init__.py”, line 41, in delayed_loader
return g[caller](*args, **kwargs)
File “/home/fksource/django/django_src/django/utils/translation/__init__.py”, line 66, in activate
return real_activate(language)
File “/home/fksource/django/django_src/django/utils/translation/trans_real.py”, line 194, in activate
_active[currentThread()] = translation(language)
File “/home/fksource/django/django_src/django/utils/translation/trans_real.py”, line 183, in translation
default_translation = _fetch(settings.LANGUAGE_CODE)
File “/home/fksource/django/django_src/django/utils/translation/trans_real.py”, line 168, in _fetch
app = __import__(appname, {}, {}, [])
ImportError: No module named registration
Am I doing something wrong?
You’ve put registration into ‘project.registration’, rather than ‘registration’ as-is. Put it like that into installed apps.
Nothing jumps out at me…can you show me what you put in settings.py?
Your directions are slightly incorrect.
You are not supposed to place the registration app inside your project, it is supposed to be on PYTHONPATH.
As the project dir is normally NOT on PYTHONPATH, your directions will lead to non-functional projects, as they try to load a module that does not exist
Thanks for stepping in with the solution. I must have made a misstep when I set up my Django environment initially.
From a complete Django newbie, thanks for the tips - I’ll certainly be using this. For the record, the B-list describes a new version of the registration code (0.2) at http://www.b-list.org/weblog/2007/05/29/django-registration-update
Thanks, that’s good to know.
Thanks for the tutorial, how about part two where you tie this together with an extended user profile module?
Good idea for a post. Lately, I’ve been doing more with Ruby on Rails than Django, but I’ll keep it in mind.
I am trying to install django-registration but when I add it to settings.py. I get the following error:
Error: Couldn’t install apps, because there were errors in one or more models:
registration: cannot import name ugettext_lazy
can someone help me pinpoint where i’m going wrong?
John,
I hate to ask this, but is your Django installation up to date? I think the function being referred to is relatively new.
I got caught by this too. As a newbie user of Django, the most annoying thing is the way that third-party extensions track the development version, rather than the release. Don’t get me wrong - django-registration works like a dream for me, except for this. Apparently, django-0.96.1 was released a week or two ago (not that you would know from the django home page) and I think this may fix the problem…although I’ve yet to confirm.
django-0.96.1 and problem: -> registration: cannot import name ugettext_lazy
;-(
I got it to work for me by reinstalling django-registration 0.2 (django-0.96.1). (The strange thing is, I thought that I had already been using dj-reg 0.2…hmmm)
That’s great, thanks for letting us know!
thanks! Great guide - more prescriptive than the txt files in the svn.
One question - the distribution does not contain any default templates. I’m a near noob o Python and a total noob to Django. Do you know where I can get some working template files to get me started?
thanks!!!!!!!!!!
Richard,
I’m glad you found this useful, although I should warn you that it was written for an older version of django-registration, so beware. It looks like in the more recent versions of the plugin, the author removed the example templates, so, if the start I gave above isn’t enough, you may want to look back at older versions of the plugin that still have the example templates. (According to the changelog, the templates were removed in the 0.3p4, 4 October 2007 version.)
Hi, and thanks for getting back.
I digged a little deeper and found some django registration templates that work, here’s the link if anyone else is looking: http://code.djangoproject.com/browser/djangoproject.com/django_website/templates/registration
They are also ~5 months old, so am not sure if I may need to modify them. However am pleased to say I now have registration and auth working end to end (needs a little polish, bit it works).
Thanks once again for the guide!
- rich
Great! Thanks for following up with the link. From what I have seen the newest version of django-registration is largely backward compatible with any incompatible changes well documented in the changelog, so hopefully you won’t run into very many issues.
[...] stone mind ยป Django Registration for Newbies (tags: development django framework login programming python registration authentication user) [...]
Great tutorial, thanks.
I ‘m using registration in my pet project, but I have one problem. One of the points of this project, beyond registering a user, is extending the django user model with a profile.
While you get access to a userProfile model when using django-registration, it is a bit unclear how to extend the RegistrationForm to include things from the UserProfile.
If I want to save for example, addresses for my users, I would like that to be a field in their registration form.
A follow-up clarifying this would be amazing!
Hi -
I just grabbed your plugin using subversion (svn checkout http://django-registration.googlecode.com/svn/trunk/registration/ registration), but the templates are nowhere to be found. Am I missing something?
Thanks,
Joey
Nevermind, I read through the docs. Your blog post made it sound like the templates were included. Thanks for the great work.
Sorry for the confusion. Also, I didn’t write the Django registration plugin, I’m just a grateful user.
Thanks for the prefab templates linked above. I notice that set is missing a basic profile.html - does anyone have a copy to add? Thanks.
Oops - password_reset.html is also missing from the set. Gracie.
[...] Django Registration for Newbies [...]
This was totally helpful. Thanks a bunch!!
(Btw, a script on your page is driving FF on my Mac nuts. Could just be me though, I dunno.)
[...] I took to get it up and running for a freshly created Django project. Other tutorials are available here, here and here, as well as in the official [...]
Interesting article, but unfortunately already new version Django and there is some changes
[...] LinkedIn [...]