Setting up validated login with allauth in Django

In this tutorial we are going to implement the login functionality of the allauth package, with nicely formatted and user friendly templates.

July 5, 2020, 1:38 p.m.
Themes: Authentication

We assume that we have a Django project up and running, with an app installed (called userauth in our case) and one template logout.html already copied from allauth in our templates directory. If needed you can read here how to do that.

So let's start with copying login.html from allauth and putting it where allauth expects it, in the directory account/ of our templates directory userauth/templates/userauth/. We can access the form by going to http://127.0.0.1:8000/accounts/login/.

Using Bootstrap we have created a new base template with three blocks card-header, card-body and card-footer, to make our templates look nicer. We are going to divide our login.html template in these three parts, resulting in the following html code:

{% extends 'account/base_card.html' %}

{% load i18n %}

{% block title %}{% trans "Sign In" %}{% endblock %}

{% block card-header %}
    <h3>{% trans "Sign In" %}</h3>
{% endblock %}

{% block card-body %}

    <form method="POST" action="{% url 'account_login' %}">
        {% csrf_token %}
        <div class="form-group">
            {% with field=form.login %}{% include "account/form_field.html" %}{% endwith %}
        </div>
        <div class="form-group">
            {% with field=form.password %}{% include "account/form_field.html" %}{% endwith %}
        </div>
        <button type="submit" class="btn btn-outline-primary">{% trans "Sign In" %}</button>
    </form>

{% endblock %}

{% block card-footer %}
    <p>{% trans "Don't have an account?" %} <a href="{{ signup_url }}">{% trans "Sign Up" %}</a></p>
    <small>
        <a class="text-muted" href="{% url 'account_reset_password' %}">{% trans "Forgot Password?" %}</a>
    </small>
{% endblock %}

What we have here is a card header with a title, a card body with a login form and a card footer with links to sign up or to reset our password; the names for these are defined in allauth. The submit button has a nice Bootstrap button class. In the original form we had

{{ form.as_p }}

which is a quick way to display all fields of the form. We have separated out the login and password field and included a separate snippet form_field.html to display these. That allows us to have control over where to put all input fields while maintaining one look and feel and logic for all of our fields. The tags with and include are standard Django template tags.

We will compose the snippet form_field.html with the help of widget-tweaks, which can beautifully render fields with just a couple of tags and filters. First we install the package:

pip3 install django-widget-tweaks

and put it in our requirements.txt, as well as add widget_tweaks to our installed apps. There are very good of examples on its use on the web, and after experimenting a bit we will use the following code:

{% load widget_tweaks %}

<small>{{ field.label_tag }}</small>

{% if form.is_bound %}
    {% if field.errors or form.non_field_errors %}
        {% render_field field class="form-control is-invalid" %}
        <div class="invalid-feedback">
            {{ form.non_field_errors }}
            {{ field.errors }}
        </div>
    {% else %}
        {% render_field field class="form-control is-valid" %}
    {% endif %}
{% else %}
    {% with "form-control input-field-"|add:field.name as field_class %}{% render_field field class=field_class %}{% endwith %}
{% endif %}

If the form is bound, i.e. if it has already been submitted before (perhaps with errors), then any errors are displayed or the field is 'green' and validated. If it is the first time the form is shown, then the field is rendered with the field name added as the last part of the class, so that it can be styled differently if needed.

Let's try if it works. If necessary logout first and then go to http://127.0.0.1:8000/accounts/login/, fill in the wrong credentials for a user and see what happens. With the right credentials we are logged in.

Signup can be done in the same way. But maybe you prefer signing up with email verification, or with third party social accounts.

Comment on this article (sign in first or confirm by name and email below)