DEV Community

Roshan Chokshi
Roshan Chokshi

Posted on

How to Use Email as Username for Django Authentication.

Django comes with a default user model that's used for the standard authentication system. If you had worked on Django you probably have seen this authentication page.

Default Admin Log-in page

We're going to override this model with our own custom model that allows us to use an Email instead of the standard Username that comes with the Django default model.

We're gonna modify models.py file to include our user profile model.
The first thing we need to do is import some additional classes at the top.

AbstractBaseUser

According to Django documentation AbstractBaseUser has the authentication functionality only , it has no actual fields, you will supply the fields to use when you subclass.

PermissionsMixin

Django provides PermissionsMixin. This is an abstract model you can include in the class hierarchy for your user model, giving you all the methods and database fields necessary to support Django’s permission model.

BaseUserManager

If your user model defines username, email, is_staff, is_active, is_superuser, last_login, and date_joined fields the same as Django’s default user, you can install Django’s UserManager; however, if your user model defines different fields, you’ll need to define a custom manager that extends BaseUserManager.

Add this lines at top of the file.



from django.contrib.auth.models import AbstractBaseUser
from django.contrib.auth.models import PermissionsMixin
from django.contrib.auth.models import BaseUserManager


Enter fullscreen mode Exit fullscreen mode

Creating UserProfile Class.

Underneath the imports let's create a new class called UserProfile and inherit from the AbstractBaseUser and PermissionsMixin



class UserProfile(AbstractBaseUser, PermissionsMixin):
    """ Database model for users in the system """
    email = models.EmailField(max_length=255, unique=True)
    name = models.CharField(max_length=255)

    objects = UserProfileManager()

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['name']

    def __str__(self):
        """ Return string representation of our user """
        return self.email


Enter fullscreen mode Exit fullscreen mode

By adding above code we:

  • Made the email and name field required and made email unique
  • Set the USERNAME_FIELD which defines the unique identifier for the username to email.
  • Specified that all objects for the class come from the UserProfileManager

Creating UserProfileManager Class.

Now that we have our custom user model we can go ahead and create a manager. Now because we've customized our model we need to tell Django how to interact with this user model in order to create users because by default when it creates a user it expects a user name field and password field but we replace the user name field with an email field.So we just need to create a custom manager that can handle creating users with an email field instead of a user name field.

Let's create a new class called UserProfileManager and inherit from the BaseUserManager.



class UserProfileManager(BaseUserManager):
    """ Manager for user profiles """


Enter fullscreen mode Exit fullscreen mode

UserProfileManager the way it manages work is you specify
some functions within the manager that can be used to manipulate objects within the module that the manager is for.

Below are two functions which we need to add in UserProfileManager class.



def create_user(self, email, name, password=None):
        """ Create a new user profile """
        if not email:
            raise ValueError('User must have an email address')

        email = self.normalize_email(email)
        user = self.model(email=email, name=name)

        user.set_password(password)
        user.save(using=self._db)

        return user

    def create_superuser(self, email, name, password):
        """ Create a new superuser profile """
        user = self.create_user(email,name, password)
        user.is_superuser = True
        user.is_staff = True

        user.save(using=self._db)

        return user


Enter fullscreen mode Exit fullscreen mode

Above code sets logic for when one creates users and superusers using Django CLI.

Update Settings to use Custom Model.

We need add below line in settings.py to use this model over default one.



AUTH_USER_MODEL = 'App_name.UserProfile'

Enter fullscreen mode Exit fullscreen mode




Make changes in Database.

Create new migrations and migrate them which will create a new database that uses our custom User Model:



$ python manage.py makemigrations
$ python manage.py migrate

Enter fullscreen mode Exit fullscreen mode




Create superuser




$ python manage.py createsuperuser
Email address: chokshiroshan@gmail.com
Password:
Password (again):
Superuser created successfully.

Enter fullscreen mode Exit fullscreen mode




Test

As you can see instead of asking for Username it is prompting for Email.

Screenshot 2021-08-05 at 6.34.30 PM

Top comments (2)

Collapse
 
akshtx profile image
Akorshon Moho • Edited

So, I implemented this one (well, this one has issues - so, I followed what's on: medium.com/@royprins/django-custom... ) but now I see a problem. Only the superuser/admin can login with email address. 'authenticate' and 'login' fails for regular user. I have created a custom 'authenticate()' but then 'login()' still fails. Any idea or suggestion?

Collapse
 
buffstop profile image
buffstop

This will crash after login and bring all kinds of issues as the user is missing required fields (e.g. is_stuff)