Setting up Django Registration

Django’s admin framework includes the basic functionalities for logging in and out of the admin site, but if you’re building a so-called ‘social’ application and want people to be able to sign-up, log in and thus benefit from additional site functionalities then you need to use a more generic ‘registration’ application. The good news is: most of the work has already been done, so it’s just a matter of putting things together correctly.

I found a nicely written blog post on this topic, so in what follows I’m just doing a re-cap of the main steps involved and adding some other useful info.

Before we start: what follows has been tested on Django 1.1 Django 1.3, Python 2.6 and MySQL (note: on 13/8/12 I revised this post so that the code would work on django 1.3 – many thanks to the folks who left comments and pointed out what needed to be updated!)

1) Install

Download the package from bitbucket and add it to your application directory (or put it somewhere else and then modify your python path as needed). Then add the ‘registration’ app to the installed_apps tuple in your settings.py:

INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.humanize',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.admin',
    # etc..
    'registration',
)

2) Syncdb

Do a quick syncdb from the console, which will result in one new table being created in the DB, ‘RegistrationProfile’. All it contains is its primary key, the ‘user’ key, and the ‘activation code’ fields. Now we’ve got the data structures needed for setting up the registration application!

> python manage.py syncdb

3) Setting.py

Create some registration settings in settings.py:

ACCOUNT_ACTIVATION_DAYS=7
EMAIL_HOST='localhost'
EMAIL_PORT=1023
EMAIL_HOST_USER='username'
EMAIL_HOST_PASSWORD='password'

Obviously you’ve got to change the settings above depending on your specific server setup (more information is available here or here). Also, see point 7 below if you’re just testing things out without a SMTP server available.

4) Urls.py

Include the required registration urls to your urls.py:

urlpatterns = patterns(",
  (r'^admin/', include('django.contrib.admin.urls')),
  (r'^accounts/', include('registration.urls')),
)

5) Templates

Add the registration templates to your django-templates directory. The django-registration package we downloaded earlier on doesn’t include any templates, but you can easily find some of them online (for example here).
Anyways, no need to do that: I took those templates and added some other ones too so to create the minimal working package that’ll get you going (that doesn’t include any fancy css styling but all the basic html stuff is there). You can download the templates here, expand the zip file and put it in templates/registration.

6) Done! Let’s recap..

We’re now ready to go. Let’s pause for a moment and recap what we achieved: we installed and activated django-registration, which sets up a whole bunch of new urls. These are divided into two groups:

a) /login, /logout, the two-step password change at password/change/ and password/change/done/; the four-step password reset at password/reset/, password/reset/confirm/, password/reset/complete/ and password/reset/done/.
This is the original URL specification source code (you can see it on bitbucket too) :

# from django-registration / registration / auth_urls.py
urlpatterns = patterns('',
                       url(r'^login/$',
                           auth_views.login,
                           {'template_name': 'registration/login.html'},
                           name='auth_login'),
                       url(r'^logout/$',
                           auth_views.logout,
                           {'template_name': 'registration/logout.html'},
                           name='auth_logout'),
                       url(r'^password/change/$',
                           auth_views.password_change,
                            {'template_name': 'registration/password_change_form.html'},
                           name='auth_password_change'),
                       url(r'^password/change/done/$',
                           auth_views.password_change_done,
                            {'template_name': 'registration/password_change_done.html'},
                           name='auth_password_change_done'),
                       url(r'^password/reset/$',
                           auth_views.password_reset,
                            {'template_name': 'registration/password_reset_form.html'},
                           name='auth_password_reset'),
                       url(r'^password/reset/confirm/(?P<uidb36>[0-9A-Za-z]+)-(?P<token>.+)/$',
                           auth_views.password_reset_confirm,
                            {'template_name': 'registration/password_reset_confirm.html'},
                           name='auth_password_reset_confirm'),
                       url(r'^password/reset/complete/$',
                           auth_views.password_reset_complete,
                            {'template_name': 'registration/password_reset_complete.html'},
                           name='auth_password_reset_complete'),
                       url(r'^password/reset/done/$',
                           auth_views.password_reset_done,
                            {'template_name': 'registration/password_reset_done.html'},
                           name='auth_password_reset_done'),
)

b) the second group of urls are /activate and /register:
This is the original URL specification source (see it on bitbucket) :

# django-registration / registration / backends / default / urls.py 
urlpatterns = patterns('',
                       url(r'^activate/complete/$',
                           direct_to_template,
                           { 'template': 'registration/activation_complete.html' },
                           name='registration_activation_complete'),
                       # Activation keys get matched by w+ instead of the more specific
                       # [a-fA-F0-9]{40} because a bad activation key should still get to the view;
                       # that way it can return a sensible "invalid key" message instead of a
                       # confusing 404.
                       url(r'^activate/(?P<activation_key>w+)/$',
                           activate,
                           { 'backend': 'registration.backends.default.DefaultBackend' },
                           name='registration_activate'),
                       url(r'^register/$',
                           register,
                           { 'backend': 'registration.backends.default.DefaultBackend' },
                           name='registration_register'),
                       url(r'^register/complete/$',
                           direct_to_template,
                           { 'template': 'registration/registration_complete.html' },
                           name='registration_complete'),
                       url(r'^register/closed/$',  # UNUSED
                           direct_to_template,
                           { 'template': 'registration/registration_closed.html' },
                           name='registration_disallowed'),
                        # this is the default django login module 
                       (r'', include('registration.auth_urls')),
                       )

7) Testing

If you’re testing things on a development server you might not have access to an SMTP server (needed to test the email-based registration process). In such a case you can still try out your application using a workaround. In your settings.py file change the registration settings with the following ones:

EMAIL_HOST = 'localhost'
EMAIL_PORT = 1025
EMAIL_HOST_USER = "
EMAIL_HOST_PASSWORD = "
EMAIL_USE_TLS = False
DEFAULT_FROM_EMAIL = 'testing@example.com'

Then open up another console window and run a temporary ‘dummy’ SMTP server with python:

bash-3.2$ python -m smtpd -n -c DebuggingServer localhost:1025

This local SMTP server remains there waiting for incoming messages. If now you go to /accounts/register/, fill out the form and hit ‘send’ you’ll see the registration email printed out in the console. Basically what happened is this: the ‘dummy’ python SMTP server we’ve just set up picked up django’s email-sending request and consequently printed out the email contents. If this is indeed what happened, it means that your code is working properly… and that you can use the url provided in the email to test the activation functionality too.

For example, here is what you would see in the console after registering:


---------- MESSAGE FOLLOWS ----------
Content-Type: text/plain; charset="utf-8"
MIME-Version: 1.0
Content-Transfer-Encoding: quoted-printable
Subject: Activate your djangoproject.com account - you have 2 days!
From: testing@example.com
To: michele.pasin@hotmail.com
Date: Wed, 12 Jan 2011 16:49:59 -0000
Message-ID: <20110112164959.3366.35638@mymac.local>
X-Peer: 127.0.0.1


Someone, hopefully you, signed up for a new account at djangoproject.com using this email address. If it was you, and you'd like to activate and use your
account, click the link below or copy and paste it into your web browser's address bar:

http://127.0.0.1:8000/accounts/activate/6342fca5ffd430a820be6d98acde6e59a4c2d29c/

If you didn't request this, you don't need to do anything; you won't receive any more email from us, and the account will expire automatically in two days.

------------ END MESSAGE ------------

Pasting the ‘activation’ url in your browser should allow you to complete the registration process and check the rest of your code.

Finally, keep in mind also that the django-registration application sends out emails that contain your site’s URL for the activation link, and that URL is dynamically determined using the ‘sites’ application (normally added via settings.py). 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.

===== ++ =====

Some other possibly useful links:

Fromt the Django website:

  • User authentication in django
  • Sending emails
  • From the Django book:

  • Chapter 12: Sessions, users, and registration
  •  

    Share/Bookmark