Django Extending or Substituting User Model Use the `email` as username and get rid of the `username` field


If you want to get rid of the username field and use email as unique user identifier, you will have to create a custom User model extending AbstractBaseUser instead of AbstractUser. Indeed, username and email are defined in AbstractUser and you can't override them. This means you will also have to redefine all fields you want that are defined in AbstractUser.

from django.contrib.auth.models import (
    AbstractBaseUser, PermissionsMixin, BaseUserManager,
from django.db import models
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _

class UserManager(BaseUserManager):

    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        if not email:
            raise ValueError('The given email must be set')
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        return user

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

    def create_superuser(self, email, password, **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)

class User(AbstractBaseUser, PermissionsMixin):
    """PermissionsMixin contains the following fields:
        - `is_superuser`
        - `groups`
        - `user_permissions`
     You can omit this mix-in if you don't want to use permissions or
     if you want to implement your own permissions logic.

    class Meta:
        verbose_name = _("user")
        verbose_name_plural = _("users")
        db_table = 'auth_user'
        # `db_table` is only needed if you move from the existing default
        # User model to a custom one. This enables to keep the existing data.

    USERNAME_FIELD = 'email'
    """Use the email as unique username."""

    REQUIRED_FIELDS = ['first_name', 'last_name']

        (GENDER_MALE, _("Male")),
        (GENDER_FEMALE, _("Female")),

    email = models.EmailField(
        verbose_name=_("email address"), unique=True,
            'unique': _(
                "A user is already registered with this email address"),
    gender = models.CharField(
        max_length=1, blank=True, choices=GENDER_CHOICES,
    first_name = models.CharField(
        max_length=30, verbose_name=_("first name"),
    last_name = models.CharField(
        max_length=30, verbose_name=_("last name"),
    is_staff = models.BooleanField(
        verbose_name=_("staff status"),
            "Designates whether the user can log into this admin site."
    is_active = models.BooleanField(
            "Designates whether this user should be treated as active. "
            "Unselect this instead of deleting accounts."
    date_joined = models.DateTimeField(
        verbose_name=_("date joined"),,

    objects = UserManager()