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)
_create_user -
Thisprivate
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.create_user -
This method sets default values foris_staff and is_superuser
toFalse
and then calls_create_user to create a regular user
.create_superuser -
This method sets default values foris_staff and is_superuser to True.
It checks if these fields areTrue
to ensure the createduser 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.