How to Remove or Disable Username from Django Default User model


To remove or disable the username for users in Django while using the AbstractUser class, you need to customize the Django user model.

By default, Django’s user model includes a username field, but you can create a custom user model to replace it with an email field.

Step 1: Create a Custom User Model

Create a new Django app (if you don't have one already) -

python manage.py startapp accounts

Define the custom user model in accounts/models.py -

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

class CustomUser(AbstractUser):
    username = None
    email = models.EmailField(unique=True)
    username = None
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = [] # Add List of fields which you want to be required

    def __str__(self):
        return self.email

Django's authentication framework uses the `USERNAME_FIELD` attribute to determine which field identifies users during login.

In this example, the `USERNAME_FIELD` is set to `email` because, by default, it is set to `username`.

The `REQUIRED_FIELDS` attribute is a sequence used in various parts of the framework, such as the `createsuperuser` management command.

This command checks `REQUIRED_FIELDS` to determine which fields should be prompted for when creating a user.

By default, `REQUIRED_FIELDS` is set to `['email']`, which is why the `createsuperuser` command prompts for an email address.

However, the command also prompts for the field specified in `USERNAME_FIELD` before any fields listed in `REQUIRED_FIELDS`.

Therefore, if `USERNAME_FIELD` is set to `email` and `REQUIRED_FIELDS` is also set to `['email']`, the command will fail because each field must be unique. This is why `REQUIRED_FIELDS` is set to an empty list.

Additionally, the `username` field is set to `None` to ensure Django does not include it in migrations.

Lastly, the `email` field is set to be unique because it is not unique by default.

Since the email is now used to identify users, it must be unique.

Step 2: Update settings.py

AUTH_USER_MODEL = 'accounts.CustomUser'

Step 3: Create User Manager for New Change

The logic to create new users is implemented in the UserManager. By default, UserManager expects a username.

Therefore, it is necessary to subclass UserManager and re-implement the methods used for creating new users to accommodate the use of an email instead of a username.

Here's how to create a custom UserManager for a custom user model -

class CustomUserManager(BaseUserManager):
   def _create_user(self, email, password, **extra_fields):
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.password = make_password(password)
        user.save(using=self._db)
        return user

   def create_user(self, email, password, **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)
  1. _create_user - This private method is responsible for creating and saving a user with the provided email and password. It normalizes the email, hashes the password, and saves the user to the database.
  2. create_user - This method sets default values for is_staff and is_superuser to False and then calls _create_user to create a regular user.
  3. create_superuser - This method sets default values for is_staff and is_superuser to True. It checks if these fields are True to ensure the created user is a superuser, and then calls _create_user.

Step 4: Update User Model

# Other Imports
from .managers import CustomUserManager  # Adjust the import path accordingly

class CustomUser(AbstractUser):
    # Other Fields As Defined Previously

    objects = CustomUserManager()

    def __str__(self):
        return self.email

Now objects Uses the custom user manager.

Step 4: Create and Apply Migrations

python manage.py makemigrations
python manage.py migrate

Step 5: Update User Admin Site

Add following code to admin site in accounts/admin.py

from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import CustomUser


@admin.register(CustomUser)
class CustomUserAdmin(admin.ModelAdmin):
    list_display = ('email', 'mobile_number', 'first_name', 'last_name', 'is_active', 'is_staff', 'is_superuser', 'created_at', 'updated_at')
    search_fields = ('email', 'mobile_number', 'first_name', 'last_name')
    readonly_fields = ('date_joined', 'last_login', 'created_at', 'updated_at', 'username')
    list_display_links = ('email',)
    ordering = ('email',)

In this way we could update our django app to have username as optional or removed.

Remember, No need to change forms.