DEV Community

Andrés Álvarez Iglesias
Andrés Álvarez Iglesias

Posted on

Django AllAuth Chapter 4 - Customizing Django AllAuth UI

In the previous chapters we have implemented a basic login and a social login with the help of AllAuth, using the default (and ugly) user interface. Now is the time of adding a touch of color to our little app.

List of chapters

  • Chapter 1 - The All-in-one solution for Auth in Django
  • Chapter 2 - How to install and configure Django AllAuth
  • Chapter 3 - Social login with Django AllAuth
  • Chapter 4 - Customizing Django AllAuth UI ←This one!
  • Chapter 5 - Extending Django AllAuth user model with custom fields

Painting a login form

Templates in AllAuth

All default views in AllAuth are intentionally plain and unstyled. They are prepared to be customized on every app. In the AllAuth GIT page (https://github.com/pennersr/django-allauth) we can obtain a full list of the used templates.

Templates in GIT

There are four groups:

  • Basic authentication templates: login, logout, registering, password recovery, etc
  • Social authentication templates: social login workflow
  • Account management: user profile, user actions, etc
  • Other: mail templates, common snippets, etc.

To start with our customization, we will download the GIT repo and copy some AllAuth templates to our template directory:

  • Allauth
  • account
  • socialaccount

You can copy all of them if you want to play a bit more, of course :)

Customizing base layout

The file "allauth/layouts/base.html" contains the basic layout of all AllAuth pages, so we will start customizing it, using the fantastic MaterializeCSS library (https://materializeweb.com/getting-started.html). Simply, add the MaterializeCSS required inclusions, a topbar and a container card. Add other card for the messages and move the menu to the navbar:

{% load i18n %}
<!DOCTYPE html>
<html>

<head>
   <meta http-equiv="X-UA-Compatible" content="IE=edge">
   <meta name="viewport" content="width=device-width, initial-scale=1.0">

   <title>
       {% block head_title %}
       {% endblock head_title %}
   </title>

   <!-- Compiled and minified CSS -->

   <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@materializecss/materialize@2.1.0/dist/css/materialize.min.css">

   {% block extra_head %}
   {% endblock extra_head %}
</head>

<body>

   <header>
       <nav>
           <div class="nav-wrapper indigo darken-4 white-text">

               <a href="#" class="brand-logo">AllAuth test</a>

               <ul id="nav-mobile" class="right hide-on-med-and-down">
               {% if user.is_authenticated %}
                   {% url 'account_email' as email_url %}
                   {% if email_url %}
                       <li>
                           <a href="{{ email_url }}">{% trans "Change Email" %}</a>
                       </li>
                   {% endif %}
                   {% url 'account_change_password' as change_password_url %}
                   {% if change_password_url %}
                       <li>
                           <a href="{{ change_password_url }}">{% trans "Change Password" %}</a>
                       </li>
                   {% endif %}
                   {% url 'mfa_index' as mfa_url %}
                   {% if mfa_url %}
                       <li>
                           <a href="{{ mfa_url }}">{% trans "Two-Factor Authentication" %}</a>
                       </li>
                   {% endif %}
                   {% url 'usersessions_list' as usersessions_list_url %}
                   {% if usersessions_list_url %}
                       <li>
                           <a href="{{ usersessions_list_url }}">{% trans "Sessions" %}</a>
                       </li>
                   {% endif %}
                   {% url 'account_logout' as logout_url %}
                   {% if logout_url %}
                       <li>
                           <a href="{{ logout_url }}">{% trans "Sign Out" %}</a>
                       </li>
                   {% endif %}
               {% else %}
                   {% url 'account_login' as login_url %}
                   {% if login_url %}
                       <li>
                           <a href="{{ login_url }}">{% trans "Sign In" %}</a>
                       </li>
                   {% endif %}
                   {% url 'account_signup' as signup_url %}
                   {% if signup_url %}
                       <li>
                           <a href="{{ signup_url }}">{% trans "Sign Up" %}</a>
                       </li>
                   {% endif %}
               {% endif %}

               </ul>
           </div>
       </nav>
   </header>

   <main>
       <div class="container">

       {% block body %}

           {% if messages %}
               <div class="row"><div class="col s12">
                   <div class="card yellow black-text">
                       <div class="card-content">
                           <span class="card-title">{% trans "Messages:" %}</span>
                           <ul>
                               {% for message in messages %}<li>{{ message }}</li>{% endfor %}
                           </ul>
                       </div>
                   </div>
               </div></div>
           {% endif %}

           <div class="row"><div class="section col s12">
               <div class="card white">
                   <div class="card-content">
                       {% block content %}
                       {% endblock content %}
                   </div>
               </div>
           </div></div>

       {% endblock body %}

       </div>
   </main>

   <!-- Compiled and minified JavaScript -->

   <script src="https://cdn.jsdelivr.net/npm/@materializecss/materialize@2.1.0/dist/js/materialize.min.js"></script>

   {% block extra_body %}
   {% endblock extra_body %}

</body>

</html>
Enter fullscreen mode Exit fullscreen mode

Before the UI update:

Before the UI update

After the UI update:

After the UI update

A wonderful look change with just a few lines!

Customizing the login form

We still need to change individual components. The login form is located in the file "account/login.html". We will update the components to accommodate them to MaterializeCSS expected layout:

{% extends "account/base_entrance.html" %}
{% load i18n allauth account %}

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

{% block content %}

   <span class="card-title">{% trans "Sign In" %}</span>

   {% if not SOCIALACCOUNT_ONLY %}

       {% setvar link %}
           <a href="{{ signup_url }}">
           {% endsetvar %}
           {% setvar end_link %}
           </a>
       {% endsetvar %}

       <div class="row"><div class="col s12">
           {% blocktranslate %}
               If you have not created an account yet, then please {{ link }}sign up{{ end_link }} first.
           {% endblocktranslate %}
       </div></div><br/>

       {% url 'account_login' as login_url %}
       {% element form form=form method="post" action=login_url tags="entrance,login" %}
           {% slot body %}
               {% csrf_token %}
               {% element fields form=form unlabeled=True %}
               {% endelement %}
               {{ redirect_field }}
           {% endslot %}

           {% slot actions %}
               <input class="btn indigo darken-2 white-text" type="submit" tags="prominent,login" value="{% trans "Sign In" %}" />
               <br/><br/><br/>
           {% endslot %}

       {% endelement %}
       <br/>

   {% endif %}

   {% if LOGIN_BY_CODE_ENABLED %}
       {% element h2 %}
           {% element button href=request_login_code_url tags="prominent,login,secondary" %}
               {% trans "Mail me a sign-in code" %}
           {% endelement %}
       {% endelement %}
   {% endif %}

   {% if SOCIALACCOUNT_ENABLED %}
       {% include "socialaccount/snippets/login.html" with page_layout="entrance" %}
   {% endif %}

{% endblock content %}
Enter fullscreen mode Exit fullscreen mode

To update the "social" part of the login form, we need to update also the "socialaccount/snippets/login.html" file:

{% load i18n allauth  socialaccount %}
{% get_providers as socialaccount_providers %}

{% if socialaccount_providers %}

   {% if not SOCIALACCOUNT_ONLY %}
       <span class="card-title">{% trans "Or use a third-party" %}</span>
   {% endif %}

   {% include "socialaccount/snippets/provider_list.html" with process="login" %}
   {% include "socialaccount/snippets/login_extra.html" %}

{% endif %}
Enter fullscreen mode Exit fullscreen mode

In AllAuth, each element has it's own template for easy customization, we can also add some classes to forms, fields and buttons to fully customize each shown element.

The final result:

The final result

Better, isn’t?

Endless customization possibilities

All internal views of AllAuth have their own customizable HTML. All individual HTML components have it's own template. With this clever system, it's easy to customize each tiny part of AllAuth user interface.

The possibilities are endless!

About the list

Among the Python and Docker posts, I will also write about other related topics (always tech and programming topics, I promise... with the fingers crossed), like:

  • Software architecture
  • Programming environments
  • Linux operating system
  • Etc.

If you found some interesting technology, programming language or whatever, please, let me know! I'm always open to learning something new!

About the author

I'm Andrés, a full-stack software developer based in Palma, on a personal journey to improve my coding skills. I'm also a self-published fantasy writer with four published novels to my name. Feel free to ask me anything!

Top comments (0)