Day 4: Implementing a Custom User Model in Django and Creating a Superuser
Welcome back to our Django tutorial series! In Day 4, we'll delve into creating a custom user model in Django and how to register it. We'll also walk through creating a superuser to test our new model. By the end of this tutorial, you'll have a custom user model that fits your project's specific needs.
Why Create a Custom User Model?
While Django provides a default User
model, it might not cover all the fields your project requires. If you need to store additional user information—such as a profile picture, address, or job title—it's better to create a custom user model. You can achieve this by creating an accounts
app and defining a CustomUser
model with the extra fields you need.
Registering the Accounts App
In the previous article, we created an app called accounts
. Before we start modifying models, we need to register this app in our project's settings.py
file.
Open projectpulse/
settings.py
and add "accounts"
to the INSTALLED_APPS
list:
# projectpulse/settings.py
INSTALLED_APPS = [
"accounts",
"django.contrib.admin",
"django.contrib.auth",
"django.contrib.contenttypes",
# ... other installed apps
]
This tells Django to include the accounts
app when running migrations and other management commands.
Creating the Custom User Model
Now, let's create a custom user model step by step. We'll break it down into three main parts:
Defining User Roles using Enums
Creating a Custom User Manager
Defining the Custom User Model
All of these will be added to accounts/
models.py
.
Note: Make sure to import necessary modules as we proceed.
1. Defining User Roles with Enums
First, we'll define user roles using Python's enum
module. This allows us to have a set of predefined choices for user roles.
# accounts/models.py
from enum import Enum
class UserRoles(Enum):
"""Defines the user roles within the application."""
ADMIN = "Admin"
PROJECT_MANAGER = "Project Manager"
TEAM_MEMBER = "Team Member"
2. Creating a Custom User Manager
Next, we'll create a custom user manager by extending BaseUserManager
. This manager will handle the creation of regular users and superusers.
# accounts/models.py
from django.contrib.auth.base_user import BaseUserManager
class CustomUserManager(BaseUserManager):
"""Custom user manager for the CustomUser model."""
def create_user(self, email, password=None, **extra_fields):
"""Creates and returns a regular user."""
if not email:
raise ValueError("The Email field must be set.")
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, password=None, **extra_fields):
"""Creates and returns a superuser."""
extra_fields.setdefault("is_staff", True)
extra_fields.setdefault("is_superuser", True)
extra_fields.setdefault("role", UserRoles.ADMIN.value)
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.")
if extra_fields.get("role") != UserRoles.ADMIN.value:
raise ValueError("Superuser must have role=Admin.")
return self.create_user(email, password, **extra_fields)
Explanation:
create_user: Handles the creation of regular users. It normalizes the email, sets the password, and saves the user.
create_superuser: Handles the creation of superusers. It ensures that certain fields are set appropriately.
3. Defining the Custom User Model
Now, we'll define the CustomUser
model by extending AbstractUser
. We'll replace the username field with an email field and add additional fields as needed.
# accounts/models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.translation import gettext_lazy as _
class CustomUser(AbstractUser):
"""
Custom user model that uses email instead of username.
Additional fields can be added as required.
"""
username = None
email = models.EmailField(_("email address"), unique=True)
profile_picture = models.ImageField(upload_to="profile_pictures/", blank=True, null=True)
role = models.CharField(
max_length=20,
choices=[(role.value, role.value) for role in UserRoles],
default=UserRoles.TEAM_MEMBER.value
)
USERNAME_FIELD = "email"
REQUIRED_FIELDS = ["first_name", "last_name"]
objects = CustomUserManager()
def __str__(self):
return f"{self.id} - {self.get_full_name()}"
Explanation:
username = None: We remove the username field since we'll use email for authentication.
email: Set as the unique identifier for authentication.
profile_picture: An optional field to store the user's profile picture.
role: A field to store the user's role, with choices defined by
UserRoles
.USERNAME_FIELD: Specifies the field used for authentication (email in this case).
REQUIRED_FIELDS: Additional fields required when creating a superuser.
objects: Specifies the custom manager we created earlier.
Updating AUTH_USER_MODEL
in Settings
To tell Django to use our custom user model, add the following line to your settings.py
:
# projectpulse/settings.py
AUTH_USER_MODEL = 'accounts.CustomUser'
Applying Migrations
Now that we've defined our custom user model, we need to create and apply migrations to update the database.
1. Create Migrations
Run the following command to create migration files:
python manage.py makemigrations
You should see output similar to:
Migrations for 'accounts':
accounts/migrations/0001_initial.py
- Create model CustomUser
2. Apply Migrations
Apply the migrations to update the database schema:
python manage.py migrate
This will create the necessary tables in your database for the accounts
app.
Creating a Superuser
To test our custom user model, let's create a superuser account.
Run the following command:
python manage.py createsuperuser
You'll be prompted to enter the following information:
Email address: Provide a valid email.
First name and Last name: Since we added these to
REQUIRED_FIELDS
.Password: Enter a secure password.
Email address: admin@example.com
First name: Admin
Last name: User
Password: ********
Password (again): ********
Superuser created successfully.
What's Next?
In this tutorial, we've:
Registered the
accounts
app in our project settings.Created a custom user model with additional fields.
Applied migrations to update the database.
Created a superuser to test the new user model.
In the next article, we'll focus on creating custom forms for our CustomUser
and integrating them into the Django admin panel for easier management.
Conclusion
Congratulations! You've successfully implemented a custom user model in Django, which is a significant step in customizing your web application to meet specific requirements. Custom user models offer flexibility and scalability, allowing you to add as many custom fields as your project needs
Additional Resources
Feel free to leave comments or questions below. Happy coding!