In Part 1: Login & Logout we built a login and logout page for our Django app. In this post we’ll create a signup page so users can register for a new account.

The Django auth app provided us with built-in url and views for login and logout. All we needed to do was add a template for login. To create a sign up page we will need to make our own view and url, but Django helps us out by providing a form class, UserCreationForm.

Complete source code can be found on Github.

Users app

Since we’re making our own view and url for registration, we need to create a dedicated app. Let’s call it users.

(users) $ ./ startapp users

Make sure to add the new app to the INSTALLED_APPS setting in our my_project/ file:

# my_project/

Then add a project-level url for the users app above our included Django auth app. Django will look top to bottom for url patterns so when it sees a url route within our users app that matches one in the built-in auth app, it will choose the users route first.

# my_project/
from django.conf.urls import include, url
from django.contrib import admin
from django.views.generic.base import TemplateView

urlpatterns = [
    url(r'^$', TemplateView.as_view(template_name='index.html'), name='index'),
    url(r'^users/', include('users.urls')),
    url(r'^users/', include('django.contrib.auth.urls')),

Create a new urls file in our users app. Note that we are importing a view called SignUp which we’ll implement in the next section.

(users) $ touch users/
# users/
from django.conf.urls import url

from . import views

urlpatterns = [
    url(r'signup/$', views.SignUp.as_view(), name='signup'),

Now for the file:

# users/
from django.contrib.auth.forms import UserCreationForm
from django.core.urlresolvers import reverse_lazy
from django.views import generic

class SignUp(generic.CreateView):
    form_class = UserCreationForm
    success_url = reverse_lazy('login')
    template_name = 'signup.html'

We’re subclassing the generic class-based view CreateView in our SignUp class. We specify the use of the built-in UserCreationForm and the not-yet-created template at signup.html. And we use reverse_lazy to redirect the user to the login page upon successful registration.

Why use reverse_lazy instead of reverse I hope you’re asking? The reason is that for all generic class-based views the urls are not loaded when the file is imported, so we have to use the lazy form of reverse to load them later when they’re available.

Ok final step. Create a template signup.html within the existing project-level templates folder.

(users) $ touch templates/signup.html

Then populate it with this code that looks almost exactly like what we used for login.html.

<!-- templates/signup.html -->
{% extends 'base.html' %}

{% block title %}Sign Up{% endblock %}

{% block content %}
  <h2>Sign up</h2>
  <form method="post">
    {% csrf_token %}
    {{ form.as_p }}
    <button type="submit">Sign up</button>
{% endblock %}

And we’re done! To confirm it all works, spin up our local server with ./ runserver and navigate to

Django signup page

The extra text with tips on usernames and passwords comes from Django. We can customize that too but it requires a little more work and is beyond the scope of this tutorial.

Sign up for a new account and hit the “Sign up” button. You will be redirected to the login page where you can log in with your new account.

Login page

And then after a successful login you’ll be redirect to the homepage with a personalized “Hi username!” greeting.

Homepage for user wsvincent

Next Steps

We’ve successfully created login, logout, and register new users functionality. The Django auth app also provides support for creating a reset password form and confirming registration through email. We’ll cover both in the next and final tutorial Part 3: Password Reset.

If you’d like to learn more about Django and build step-by-step multiple web applications, check out the free online book I wrote Django For Beginners.