Learn Wagtail CMS Course

Adding User Registration/Login To Your Wagtail Website

One package to rule them all

In the land of Python, Django and Wagtail there are tonnes of packages we can use. Lots of great developers open source their code and let other people contribute to the original code base and make a package truly amazing.

One of these packages is Django Allauth — the package we'll be using today.

Installing django-allauth

We need to install the package first. Make sure you enter your virtual environment and install django-allauth.

$ pip install django-allauth

Enabling Allauth

Installing django-allauth requires a few steps, but it's mostly copy and paste. Open your base.py settings file and add the following:

# base.py

# Add this to your global context processors 
'django.template.context_processors.request',

# So you're entire templates dictionary should look something like this:
TEMPLATES = [
    {
        # ...,
        'OPTIONS': {
            'context_processors': [
                # ...
                'django.template.context_processors.request', # <- this is the one you NEED to include
                # ...
            ],
        },
    },
]

Also in your base.py file you'll want to add the allauth authentication backend. Add the following to your main settings file.

# base.py 

# 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',
)

Next we'll need to make sure we have 6 apps enabled. Three are from Django itself, and three are from Allauth. In your base.py settings file, make sure you have each of these apps installed.

# base.py 

INSTALLED_APPS = (
    # ... other apps 

    # The following apps are required:
    'django.contrib.auth',
    'django.contrib.messages',
    'django.contrib.sites',

    'allauth',
    'allauth.account',
    'allauth.socialaccount',
    # ...
)

We also need to tell Allauth which site to enable authentication on. If you're not using Django or Wagtail multisite, then the default SITE_ID will always be 1. Make sure this is also in your base.py file.

# base.py 

SITE_ID = 1

Almost there! We're done with the base.py file for a moment. Now you'll need to add the Allauth URLs to your application. If you don't do this, then Allauth will be installed but it won't be accessible from the web (making all of our previous work useless).

Open urls.py and add url(r'', include('allauth.urls')), to your urlpatterns.

# urls.py

urlpatterns = [
    # .. Existing urls 
    url(r'', include('allauth.urls')), # Creates urls like yourwebsite.com/login/
    # url(r'^accounts/', include('allauth.urls')), # Creates urls like yourwebsite.com/accounts/login/

    # Wagtail URLs
    url(r'', include(wagtail_urls)),
]

Last step before we can configure our websites' new authentication system. If you were to run python manage.py runserver 0:8000 you should be shown a bunch of red text saying "You have 7 unapplied migrations" (the actual number may vary depending on the version of django-allauth). Django Allauth lets us create email-based registration and also social-based authentication. Internally, it has it's own way of dealing with user accounts and storing user data. So we need to run migrations now.

$ python manage.py migrate

And just like that, we're up and running! To test this go to http://localhost:8000/login/ (or http://localhost:8000/accounts/login/ if you used the default Allauth URL pattern).

You should see a login form.

If the page loads, but there's nothing being displayed, you'll need to modify the allauth templates. We'll tackle this at the end of the tutorial.

Configuration

In the video I configured our authentication package using common configuration settings. I didn't use them all and there are more at https://django-allauth.readthedocs.io/en/latest/configuration.html — make sure you read through all the settings and change the settings to fit your websites needs.

Let's re-open our base.py settings and add some generic settings.

# base.py 

LOGIN_URL = '/login/'
LOGIN_REDIRECT_URL = '/'
ACCOUNT_AUTHENTICATION_METHOD = "username_email"
ACCOUNT_CONFIRM_EMAIL_ON_GET = True
ACCOUNT_EMAIL_REQUIRED = True
ACCOUNT_EMAIL_VERIFICATION = "mandatory"
ACCOUNT_LOGIN_ON_EMAIL_CONFIRMATION = True
ACCOUNT_LOGOUT_ON_GET = True
ACCOUNT_LOGIN_ON_PASSWORD_RESET = True
ACCOUNT_LOGOUT_REDIRECT_URL = '/login/'
ACCOUNT_PRESERVE_USERNAME_CASING = False
ACCOUNT_SESSION_REMEMBER = True
ACCOUNT_SIGNUP_PASSWORD_ENTER_TWICE = False
ACCOUNT_USERNAME_BLACKLIST = ["admin", "god"]
ACCOUNT_USERNAME_MIN_LENGTH = 2

I won't go over what each of these settings means because it's all nicely laid out in the django-allauth documentation. Here's the link again in case you feel like reading it right now.

Modifying templates

When you want to make changes to the Django Allauth templates, like the default (and ugly) login page or the sign up page, you'll want to copy the package templates into your own template files. Here's a list of all the regular template files you can use: https://github.com/pennersr/django-allauth/tree/master/allauth/templates/account

Basically, you can copy the contents from /allauth/templates/account/login.html into your main templates folder, just make sure the folder structure matches django-allauth's directory structure.

For example, if you wanted to change the login.html template:

  • This is stored in /allauth/templates/account/login.html in the package (you can see this from the GitHub repo).
    • /allauth/ is the package name
    • /templates/ is where the templates are stored
    • /account/ is a directory inside of the /templates/ folder
    • /login.html is the file name.
  • In your application you probably have a templates directory already. So let's mirror the allauth package structure.
    • Make sure you have a /templates/ directory
    • Create a folder inside of the /templates/ folder called /account/
    • Create a login.html inside of the /account/ folder
    • Your final path will be something along these lines: yoursite/templates/account/login.html

So if you copy the original login.html file from django-allauth into your project, you can now modify it as much as you need.

Detecting logged in users

In your templates you can now detect if a user is logged in or if the user is a guest. It's as easy as an if/else statement.

{# Any template #}

{% if request.user.is_authenticated %}
    Hello {{ request.user.username }},
    <a href="{% url 'account_logout' %}">Logout?</a>
{% else %}
    Hi guest! 
    <a href="{% url 'account_login' %}">Login?</a>
{% endif %}

Additionally, you can add direct URLs in your template the any Allauth view. If you view this link, you can see all the available URL names. This is where I got {% url 'account_login' %} and {% url 'account_logout' %} from. There are many others you'll want to implement as well, such as the sign up url.

Requirements

Whenever you add a new package to your project, make sure you update the appropriate requirements file. In my case, I have a requirements.txt file so I've added django-allauth to it, and pinned it to the most recent version.

# requirements.txt

...
django-allauth==0.40.0

The Git Commit

If you want to see my exact code for this tutorial, it's always open source. Here's the link for the exact git commit: https://github.com/CodingForEverybody/learn-wagtail/commit/6ab586eb420e09c5a79c00f4040d3969caeee3a6