Wagtail with a custom user model

Combining Wagtail with a custom user model requires setting up both before migrating the database. Since this is the first tutorial of the series on PythonEatsTail, we will start from scratch.

June 27, 2020, 5:43 p.m.
Themes: Custom User Model

In this tutorial we will do the following:

  • Create a virtual environment
  • Install Django and Wagtail in it
  • Set up a database with PostgreSQL
  • Create a custom user model

Using a custom user model and Wagtail combined requires setting up the user model before doing the first database migration, so that's what we will do.

I assume you have python3 installed on your computer (if not, download it on python.org or use Homebrew for Mac. I will use the command python3 consistently, to prevent confusion with the pre-installed Python on Mac. Create a directory for the project and change into that directory:

mkdir pet
cd pet

We use the standard venv command to create a virtual environment and enter it:

python3 -m venv env
source env/bin/activate

To install Django in this environment we use pip3:

pip3 install django

Since we are prompted to update to the latest version of pip in this environment, let's take care of that:

pip3 install --upgrade pip

Now install Wagtail and start a new Wagtail project in this directory:

pip3 install wagtail
wagtail start pet .

pet is the name of the project and the . (dot) tells wagtail to install it in the current directory (otherwise a new directory would be created). Check out the project layout: Wagtail has pre-installed many files, such as requirements.txt, multiple settings files, a home directory. Don't worry about these now.

We want to use PostgreSQL for our database. Download and install it on your computer from postgresql.org or for Mac via Homebrew. Currently the latest version is 12. To create the database we will use the psql command. Make sure the directory with this command is on your path. Just using the command psql may not work, because then psql will try to connect to a database with the same name as your computer username. Since the database postgres is there by default, we can type:

psql postgres

and at the new prompt type:

CREATE USER usr_pet WITH PASSWORD '123';
CREATE DATABASE db_pet OWNER usr_pet;

Obviously you should choose a better password than 123. Here we have created a dedicated owner usr_pet of our database db_pet. This also makes sense when you later deploy your project; you don't want to execute all commands as root user. To quit psql type \q.

PostgreSQL needs a Python driver and the most widely used is psycopg2. We will install the binary version psycopg2-binary in our environment, because that gives less trouble with potentially missing configuration files:

pip3 install psycopg2-binary

We keep track of our installed packages in requirements.txt. When we open it, we see that Django and Wagtail are already in there. Add psycopg2-binary to it. The base settings for our project are in the file settings/base.py. Replace the existing setting for DATABASES with the following:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'db_pet',
        'USER': 'usr_pet',
        'PASSWORD': '123',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}

Now it is time to create our custom user model. We will subclass our model from Django's AbstractUser. In the docs:  "AbstractUser provides the full implementation of the default User as an abstract model". Together with the package allauth this allows us to use all Django's standard functionality, such as creating and editing users, adding extra fields, logging in by email, user permissions, admin functionality. For more specialized projects, it is recommended to subclass from AbstractBaseUser, which would require writing create user / create superuser methods, forms for creating and editing users in admin, defining permissions. This is outside the scope of this tutorial; there is an example in the docs.

You can put the model in any models.py file, but because we want to keep everything related to our user model in one place, we create a separate app for this:

python3 manage.py startapp userauth

Add userauth to the list of INSTALLED_APPS in settings/base.py. In the models.py file of userauth put the following (for now empty) model:

from django.contrib.auth.models import AbstractUser

class CustomUser (AbstractUser):
    pass

We tell Django to use this as our user model by adding the following to our settings/base.py:

AUTH_USER_MODEL = 'userauth.CustomUser'

Our user model will inherit all standard fields (username, password etc.) from Django's user model and we can add as many fields as we want later in our project. Now (finally) we can migrate our database:

python3 manage.py makemigrations
python3 manage.py migrate

We can check that everything is working with:

python3 manage.py runserver

and visiting the page http://127.0.0.1:8000 in our browser. There is the Wagtail home page!

That's it for now. Read more if you want to add extra fields to the custom user model and add those to Django and Wagtail admin, such as date of birth, full address, phone number, or if you want to add login, signup and many other authentication features to your project.

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