Set Up the Django Project
Before we dive into how to implement authentication in Django, we first need to set up our project and apps.
Both the screencast and the course text contain all of the necessary steps to set up the project. You should find that these steps are familiar to you from your previous Django experience!
Now that you have watched the screencast, code along with the steps in the course text to do it yourself.
First, create the project directory and navigate into it.
~/ → mkdir fotoblog && cd fotoblog
Now set up the Python environment, activate it, and install Django. Also create a
requirements.txt file using
pip freeze so you can recreate the environment elsewhere.
~/fotoblog → python -m venv ENV~/fotoblog → source ENV/bin/activate(ENV) ~/fotoblog → pip install django(ENV) ~/fotoblog → pip freeze > requirements.txt
Our project will contain two apps, one handling authentication and account management called
authentication , and another which will host our blog post and photo sharing logic
Let's start the project and create these two apps now.
(ENV) ~/fotoblog → django-admin startproject fotoblog .(ENV) ~/fotoblog → python manage.py startapp authentication(ENV) ~/fotoblog → python manage.py startapp blog
Add these apps to the
INSTALLED_APPS in settings.
# fotoblog/settings.pyINSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','authentication','blog',]
Set it up as a Git repository, and make the initial commit.
(ENV) ~/fotoblog → git init(ENV) ~/fotoblog → echo ENV >> .gitignore(ENV) ~/fotoblog → echo __pycache__ >> .gitignore(ENV) ~/fotoblog → echo db.sqlite3 >> .gitignore(ENV) ~/fotoblog → # You may want to add other non-project files and directories to your .gitignore here(ENV) ~/fotoblog → git add .(ENV) ~/fotoblog → git status(ENV) ~/fotoblog → git commit -m initial commit
The project is now set up. Next , let's configure individual users in Django.
Discover the User Model
By convention, data on an individual user is stored in a model called
User. Django provides a default `User` model. This model has many special methods and features, particularly concerning authentication and permissions, that make it seamlessly integrate into the Django framework.
You can find the default
User model in
Here's a quick overview of some of the different
User model fields:
username- used to log in.
password- this is stored as a hash in the database. Never store raw passwords.
is_staff- a boolean; dictates whether a user can log in to the Django admin site.
is_active- a boolean; it is considered Django best practice to mark users as inactive by setting this attribute to
Falseinstead of deleting them.
is_superuser- a boolean; superusers are automatically granted all permissions, such as access to the admin site.
But what if these fields don't fit my use case?
Good question! You may find that you do not require all of these fields. On the other hand, you may want all of them and more!
Luckily, you are not bound to the default model. Let's see how to customize
Use a Custom User Model
Even if you think that the default
User model is good enough, you should always implement a custom
User model in your project, even if it is identical to the default one.
This is because it is difficult and complicated to migrate to a custom
User model after your Django site has been set up and your initial migrations have been run. It requires lots of tricky migrations and an in-depth understanding of SQL. Plans change, and clients alter specifications. Save yourself a headache and set up a custom
User model at the start of your project.
When using a custom
User model, Django provides two base classes that you can extend to meet your specific needs:
AbstractUser class contains all of the fields and methods that the default
If you think the functionality of the default
User class alone will meet your needs, then using it as a custom
User model is as simple as this:
from django.contrib.auth.models import AbstractUserclass User(AbstractUser):pass
This provides all the features and fields of the default
User model and the added flexibility of being able to add additional fields and methods to it later.
Say, for instance, you also wanted to store a unique 10-digit account number for each user. To do this, just specify it the same as you would a field on any other model.
class User(AbstractUser):account_number = CharField(max_length=10, unique=True)
If you want to add more fields to the
User class, you can specify them in the same manner.
But what if I don't want to use every field provided by the default
Then you extend the
AbstractBaseUser class instead. Let's have a look at that.
AbstractBaseUser class contains no fields apart from the
password . It also comes with a suite of methods to handle authentication (as does
When extending the
AbstractBaseUser , you must specify all the fields you want to include (except
password ). There is also some additional configuration required for it to integrate with the Django authentication system.
The key configurations to implement when using the
AbstractBaseUser model are:
USERNAME_FIELD- you must set this to the field you want to use when logging in.
EMAIL_FIELD- set to the field that contains a user's primary email, defaults to
'email'if not specified.
REQUIRED_FIELDS- set this to any fields that must be specified when using the
python manage.py createsuperusercommand.
is_active- defaults to
AbstractBaseUser, but you can add your own field if you want to handle active and inactive users.
What if I want to use an email address to log in?
Easy! Just set the constant
USERNAME_FIELD to the email field. Django requires this to be unique. If you are extending
AbstractUser , you can also then remove the
field by setting it to
from django.contrib.auth.models import AbstractUserfrom django.db import modelsclass User(AbstractUser):email = models.EmailField(unique=True)username = NoneUSERNAME_FIELD = 'email'
Okay, now that we've gone over some of the different ways to implement a
User model in Django, let's do it in our app!
Set Up the Django App With a Custom User Model
It is generally better to build off the AbstractUser model as this will automatically integrate with the rest of the Django framework and have the most compatibility with third-party apps.
We want to include all of the functionality of the default
User class for our site, so we will extend
AbstractUser . We will also add two additional fields:
ImageFieldcontaining a profile photo,
CharField, which will differentiate between two types of users on our site, creators and subscribers.
Step 1: Create the
User to the models in
# authentication/models.pyfrom django.contrib.auth.models import AbstractUserfrom django.db import modelsclass User(AbstractUser):CREATOR = 'CREATOR'SUBSCRIBER = 'SUBSCRIBER'ROLE_CHOICES = ((CREATOR, 'Creator'),(SUBSCRIBER, 'Subscriber'),)profile_photo = models.ImageField()role = models.CharField(max_length=30, choices=ROLE_CHOICES)
Step 2: Configure Django to Use a Custom
Out of the box, Django uses the default
User model for authentication, so you need to tell Django that you want to use your
User model instead. To do that, point
AUTH_USER_MODEL to the correct model in the settings. When configuring
AUTH_USER_MODEL , use the notation
'<app-name>.<model-name>' , giving you:
# fotoblog/settings.pyAUTH_USER_MODEL = 'authentication.User'
Great, now that you have configured your
User model, you can run the initial migrations.
Step 3: Run the Initial Migrations
Let’s make the migrations first. When doing this, you may run into this error:
(ENV) ~/fotoblog (master)→ python manage.py makemigrationsSystemCheckError: System check identified some issues:ERRORS:authentication.User.profile_photo: (fields.E210) Cannot use ImageField because Pillow is not installed.HINT: Get Pillow at https://pypi.org/project/Pillow/ or run command "python -m pip install Pillow".
Django requires the package
Pillow in order to use the
Pillow is a Python library for processing images.
Versions of Django older than 3.2 don't automatically install
Pillow . If you see this message, you’ll need to install it using
pip and update the
requirements.txt , then try again.
(ENV) ~/fotoblog (master)→ pip install Pillow(ENV) ~/fotoblog (master)→ pip freeze > requirements.txt(ENV) ~/fotoblog (master)→ python manage.py makemigrationsMigrations for 'authentication':authentication/migrations/0001_initial.py- Create model User(ENV) ~/fotoblog (master)→ python manage.py migrateOperations to perform:Apply all migrations: admin, auth, authentication, contenttypes, sessionsRunning migrations:Applying contenttypes.0001_initial... OKApplying contenttypes.0002_remove_content_type_name... OKApplying auth.0001_initial... OKApplying auth.0002_alter_permission_name_max_length... OKApplying auth.0003_alter_user_email_max_length... OKApplying auth.0004_alter_user_username_opts... OKApplying auth.0005_alter_user_last_login_null... OKApplying auth.0006_require_contenttypes_0002... OKApplying auth.0007_alter_validators_add_error_messages... OKApplying auth.0008_alter_user_username_max_length... OKApplying auth.0009_alter_user_last_name_max_length... OKApplying auth.0010_alter_group_name_max_length... OKApplying auth.0011_update_proxy_permissions... OKApplying auth.0012_alter_user_first_name_max_length... OKApplying authentication.0001_initial... OKApplying admin.0001_initial... OKApplying admin.0002_logentry_remove_auto_add... OKApplying admin.0003_logentry_add_action_flag_choices... OKApplying sessions.0001_initial... OK
Great, you've run the migrations and are set up!
Django uses the
Usermodel to handle authentication.
It is always a good idea to use a custom
Usermodel in a project, even if you don't need added functionality, as it makes it much easier to customize it later.
You can extend the
AbstractUserto build on the default
You can extend
AbstractBaseUserfor further flexibility and to design all the fields yourself.
Now that you can store users in the database let's try to authenticate them on our site.