Quick User Registraion With Django
January 08, 2021
Kickstart
Assuming you have a virtualenv created with Django installed, you can use the shell script below to get quickly spun up from scratch. You should be able to drop most of the code in this tutorial straight into an existing Django application though if you wanted to.
!#/usr/bin/bash
# rm -rf venv
# python3 -m venv venv
# source venv/bin/activate
# pip install django
django-admin startproject auth_project
cd auth_project
django-admin startapp auth_demo
python manage.py makemigration
python manage.py migrate
python manage.py runserver
Intro
Django is my goto framework when building applications. It handles most of the nitty-gritty things out of the box and the documentation is superb. I know a lot of people complain about “django bloat” but I really dislike writing authentication and repetitve views/endpoints by hand. If you’re looking to iterate quickly and get a product out then I cannot recommend Django or any other “batteries included” framework (Rails, Laravel, etc) enough. In my opinion, rolling all of this stuff by hand is a total waste of time when you need to get a product out in a short amount of time. Frameworks like Django just work and are battle tested. Let’s get started.
Creating the Views
Django provides some reusable views and forms for handling user related things like login, logout, password change, password reset, etc. You can read more about the Authentication Views here. Django does not provide a view for registering users, but it does provide a UserCreationForm
and a generic FormView
which we can use to build our user registration form.
Starting with views.py
, below is what the registration view will look like. We are also going to include a profile view because we want to log the user in after they register.
# views.py
from django.contrib.auth import login
from django.contrib.auth.forms import UserCreationForm
from django.views.generic.edit import FormView
from django.contrib.auth.models import User
from django.contrib.auth import login
from django.views.generic.base import TemplateView
from django.urls import reverse_lazy
class RegisterView(FormView):
model = User
form_class = UserCreationForm
success_url = reverse_lazy('profile')
template_name = 'registration/create_user.html'
def form_valid(self, form):
user = form.save()
login(self.request, user)
return super().form_valid(form)
class ProfileView(TemplateView):
template_name = "user/profile.html"
In the RegisterView
class the important things to note are that we are using the User
model and the UserCreationForm
, both supplied by Django. We also define a few properties that say where our create_user.html
template lives and where we want to redirect to after a user has been successfully created. We then override the form_valid
method in FormView
and add logic to save the form data and log the user in. You’ll notice that we did not have to create any models and we did not have to explicitly write any GET
or POST
handlers for this.
The ProfileView
class simply renders a basic profile for the user upon successful registration.
Creating the Templates
Now we need to create the templates that are referenced in views.py
above. In our application directory, we’ll create a directory called “templates” (if it does not already exist) and another directory called “registration” inside the templates directory. We can then create create_user.html
in the registration directory. We’ll create the quickest and most simple version of the registration form.
# templates/registration/create_user.html
{% block content %}
<h2>Register</h2>
<form method="post">
{% csrf_token %}
{{form}}
<input type="submit" value="Register">
</form>
{% endblock %}
And we’ll add a simple profile template in templates/user/
called profile.html
.
{% if user.is_authenticated %}
<p>Welcome, {{ user.username }}. Thanks for logging in.</p>
{% else %}
<p>Welcome, new user. Please log in.</p>
{% endif %}
Updating the Urls
The last thing we need to do is update urls.py
. In this example I am going to map the views to accounts/register/
and accounts/profile/
but you can obviously point the views to whatever url you’d like.
# urls.py
...
from auth_demo.views import RegisterView, ProfileView
...
urlpatterns = [
...
path('accounts/register/', RegisterView.as_view(), name="register"),
path('accounts/profile/', ProfileView.as_view(), name="profile"),
...
]
Conclusion
So now we can start the server if it isn’t running already with python manage.py runserver
and navigate to http://127.0.0.1:8000/accounts/register/
and see our new registration view. The form will look something like this:
You’ll likely want to add your own styling and maybe override some default settings in the FormView
like help_text
, but this was really very painless and a pretty minimal amount of code considering what you get.