How to Remove Username from Django User Model

If you want to have users authenticate via email (or some other attribute) instead of username then theres a few things you’ll have to do.

First you need to create a custom user model and in it set username = None, and set USERNAME_FIELD = "email" or any other attribute you want to be used to login. Also whatever attribute you choose, has to be set to unique=True

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

class User(AbstractUser):
    REQUIRED_FIELDS = []
    USERNAME_FIELD = "email"
    username = None
    email = models.EmailField("email address", blank=False, null=False, unique=True)

You’ll still need create an Object Manager for the new custom user class since we’ve changed how django expects objects to be created. I subclassed the default user object manager and just override some methods like so:

from django.contrib.auth.models import UserManager as BaseUserManager

class UserManager(BaseUserManager):
    """ User Manager that knows how to create users via email instead of username """
    def _create_user(self, email, password, **extra_fields):
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email=None, password=None, **extra_fields):
        extra_fields.setdefault("is_staff", True)
        extra_fields.setdefault("is_superuser", True)

        if extra_fields.get("is_staff") is not True:
            raise ValueError("Superuser must have is_staff=True.")
        if extra_fields.get("is_superuser") is not True:
            raise ValueError("Superuser must have is_superuser=True.")

        return self._create_user(email, password, **extra_fields)

    def create_user(self, email=None, password=None, **extra_fields):
        extra_fields.setdefault("is_staff", False)
        extra_fields.setdefault("is_superuser", False)
        return self._create_user(email, password, **extra_fields)


class User(AbstractUser):
    objects = UserManager()  # Don't forget this part!!
    ....

Check out how the default User Manager was creating objects to see why we needed this change.

Another thing we have to do is update AUTH_USER_MODEL in our settings.py (See documentation for how to do that, but should be simple)

Final step is to run the migrations

$ python manage.py makemigrations
...
$ python manage.py migrate
...
$ python manage.py createsuperuser
....
$ python manage.py runserver

You should be able to login with email instead of username