Django Authentication using an Email Address

3 min read

Django's built-in User model uses a username as the primary means of identifying a user. However, you may want to use an email for authentication for your web application.

In this article, we will show you how to configure Django to use an email address as the primary means of identifying a user when they log in.

Considering the scope of the article I am assuming you already have a basic Django project up and running if not reading the following articles is recommended.

Enable Login with Email in Django

First you need to create a custom User model that uses an email field instead of a username field.

To do this, create a new file called models.py in your users app's directory and add the following code:

users/models.py

from django.contrib.auth.models import AbstractUser
from django.db import models

class CustomUser(AbstractUser):
    email = models.EmailField(unique=True)
This code creates a new CustomUser model that inherits from Django's built-in AbstractUser model. The new model has an additional email field that is set to be unique.

Next, you will need to update your project's settings file to use your custom User model.

Open the settings.py file and add the following code:

AUTH_USER_MODEL = 'users.CustomUser'

This line tells Django to use your custom User model when it needs to work with users.

At this point we can run the migrations, 

python manage.py makemigrations
python manage.py migrate

Create a custom authentication backend

Django uses authentication backends to authenticate users. By default, it uses a backend that looks up users by their username.

To use an email address instead, you will need to create a custom authentication backend. To do this, create a new file called backends.py in your users's directory and add the following code:

users/backends.py

from django.contrib.auth import get_user_model
from django.contrib.auth.backends import ModelBackend

class EmailBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        UserModel = get_user_model()
        try:
            user = UserModel.objects.get(email=username)
        except UserModel.DoesNotExist:
            return None
        else:
            if user.check_password(password):
                return user
        return None

This code creates a new EmailBackend class that inherits from Django's built-in ModelBackend class. The authenticate() method looks up a user by their email address instead of their username.

Finally, you will need to update your project's settings file to use your custom authentication backend.

Open the settings.py file and add the following code:

AUTHENTICATION_BACKENDS = ['users.backends.EmailBackend']

This code tells Django to use your new custom authentication backend. 

Test it out!

Once you've made these changes, you should be able to log in with email and password in the Django admin. To test it, you just need to create a superuser with an email and password and then login in into the admin dashboard.

Forms and Views 

Update the login and registration forms to ask for email instead of username. You can do this by creating custom forms that inherit from the built-in Django forms and include an email field instead of a username field.

Creating custom authentication forms 

from django import forms
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm

class CustomAuthenticationForm(AuthenticationForm):
    email = forms.EmailField(widget=forms.TextInput(attrs={'autofocus': True}))

class CustomUserCreationForm(UserCreationForm):
    email = forms.EmailField(required=True)
    class Meta:
        model = CustomUser
        fields = ('email', 'password1', 'password2')

Then, update the views and templates to use the new forms and authentication backend. 


DJANGO

Latest Articles

Latest from djangocentral

Capturing Query Parameters of request.get in Django

In Django, the request object contains a variety of information about the current HTTP request, including the query parameters. Query parameters are a way to pass additional information in the URL and are used to filter or sort data. The request object p…
Read more →

2 min read

Understanding related_name in Django Models

In Django, related_name is an attribute that can be used to specify the name of the reverse relation from the related model back to the model that defines the relation. It is used to specify the name of the attribute that will be used to access the relat…
Read more →

2 min read