In this tutorial we will set up authentication in a Django project using the popular package allauth and create a few templates for it.
Visit a previous tutorial if you haven't set up a project yet. The first thing we do is install the package in our virtual environment:
pip3 install django-allauth
Add django-allauth
to requirements.txt
. We need to change a couple of things in our settings file, in our case settings/base.py
. If you have followed an earlier tutorial and installed Wagtail, some of these settings have already been added. First, check that django.template.context_processors.request
is in context_processors
or add it. Then add the required authentication backends:
AUTHENTICATION_BACKENDS = (
...
# Needed to login by username in Django admin, regardless of `allauth`
'django.contrib.auth.backends.ModelBackend',
# `allauth` specific authentication methods, such as login by e-mail
'allauth.account.auth_backends.AuthenticationBackend',
...
)
Check that the following apps are in your INSTALLED_APPS
:
'django.contrib.auth',
'django.contrib.messages',
'django.contrib.sites',
and add the following ones:
'allauth',
'allauth.account',
'allauth.socialaccount',
All three are required, even if you don't plan on using a social account to log in. We will add specific settings for individual social accounts later. Add:
SITE_ID = 1
if it's not already there. Now go to your project urls.py
file (not the urls.py
of your app) and add the following to your urlpatterns
variable:
from django.urls import path
urlpatterns = [
...
path('accounts/', include('allauth.urls')),
...
]
Migrate the database and run the server:
python3 manage.py makemigrations
python3 manage.py migrate
python3 manage.py runserver
Since allauth
has a lot of pre-installed templates, views and forms, some of the basic functionality is already available now. For example http://127.0.0.1:8000/accounts/login/ and http://127.0.0.1:8000/accounts/logout/ already allow us to sign in and log out. However, if we successfully sign in, we end up at the unknown url http://127.0.0.1:8000/accounts/profile/. That is because allauth
builds on Django's LoginView
, which redirects to /accounts/profile/
after login. Since allauth
doesn't provide a template for that, we are going to create that ourselves below. First some preparations.
All account templates for allauth
should go into the directory account/
of your app, in our case userauth/templates/userauth/account/
, so create this directory.
Make sure you have added the path userauth/templates/userauth/
to TEMPLATES
in your settings file. Be careful: the directory with the templates is called account/
, while the url's have an extra s: /accounts/…/
. So the url …/accounts/login/
uses the template …/account/login.html
.
All default allauth
templates are here. Copy the template account/logout.html
and put it in our own account/
folder. Modify the first paragraph into
<p>{% trans 'Are you ABSOLUTELY sure you want to sign out?' %}</p>
and visit http://127.0.0.1:8000/accounts/logout/ (sign in first if necessary), to check that our app now uses our own template.
Just a note on translation: all allauth
templates are multilingual by default, i.e. they use the template tags trans
loaded with {% load i18n %}
. We will also do this throughout our own templates.
Now it is time to make our templates somewhat nicer; we will use Bootstrap for that. Go to the file base.html
in your project templates folder. Copy the link to Bootstrap's CSS file and add it at the designated point in your base.html
file. Also add the Javascript links near the end of your base.html
template as explained.
In this tutorial (but feel free to use your own creativity!) we will use the Bootstrap grid system combined with Bootstrap cards with headers and footers. This allows our templates to respond to the width of our viewport. Using cards will allow us to put different parts of the templates in the header, the body or the footer of the card. Create a template base_card.html
that does this, with the following content:
{% extends 'base.html' %}
{% block content %}
<div class="container">
<div class="row justify-content-center">
<div class="col-lg-8 col-md-10 col-sm-12">
<div class="card">
<div class="card-header">
{% block card-header %}{% endblock %}
</div>
<div class="card-body">
{% block card-body %}{% endblock %}
</div>
<div class="card-footer text-muted text-center">
{% block card-footer %}{% endblock %}
</div>
</div>
</div>
</div>
</div>
{% endblock %}
With a few modifications in the logout.html
file we copied, we use the self-created blocks card-header
and card-body
, as follows:
{% extends 'account/base_card.html' %}
{% load i18n %}
{% block title %}{% trans "Sign Out" %}{% endblock %}
{% block card-header %}
<h3>{% trans "Sign Out" %}</h3>
{% endblock %}
{% block card-body %}
<p>{% trans "Are you sure you want to sign out?" %}</p>
<form method="POST" action="{% url 'account_logout' %}">
{% csrf_token %}
<button type="submit" class="btn btn-outline-primary btn-sm">{% trans "Sign Out" %}</button>
</form>
<br><p>{% trans "No, stay logged in" %}</p>
<a href="/" class="btn btn-outline-primary">{% trans "Return to site" %}</a>
{% endblock %}
Check out how our logout page looks now, at /accounts/logout/
.
Let's now return to our missing template at /accounts/profile/
. Within your app (userauth
) create a urls.py
file with the following content:
from django.urls import path
from .views import profile_view
urlpatterns = [
path('profile/', profile_view, name='account_profile'),
]
And add the following to the url patterns of our project urls.py
file:
path('accounts/', include('userauth.urls')),
to make our profile available at the url /accounts/profile/
. Add to the views.py
file:
def profile_view(request):
return render(request, 'account/profile.html')
The only thing we need to do now is to create the template profile.html
in our templates folder userauth/templates/userauth/account/
. Create the file and add the following content:
{% extends 'account/base_card.html' %}
{% load i18n static %}
{% block title %}{% trans "Profile" %}{% endblock %}
{% block card-header %}
<h3>{% trans "Account profile" %}</h3>
{% endblock %}
{% block card-body %}
<div class="container">
<div class="row">
<div class="col border">
<small>{% trans "First name" %}:</small><br>
{{ request.user.first_name|default:'' }}
</div>
<div class="col border">
<small>{% trans "Last name" %}:</small><br>
{{ request.user.last_name|default:'' }}
</div>
</div>
</div>
{% endblock %}
Note the |default
. When fields are undefined, the value None
is displayed in the template. To prevent this, we use Django's filter default
, which displays nothing (an empty string).
Now if we successfully sign in, we are redirected to this profile page we just created. Obviously this is a very simple template, with only first name and last name. We can add all other user fields to our template as well, check the repository for the full profile.html
.
We might as well set profile.html
as our default landing page after a new user has been created. To do this, add the get_absolute_url
method in your user model:
def get_absolute_url(self):
return reverse('account_profile')
These are the basics to set up allauth
and its templates. Read on if you want to embellish allauth
's forms (such as sign in / sign up), set up email verification on signup, or use social accounts for signing in.
Comment on this article (sign in first or confirm by name and email below)