By default ,Django comes with a User
model that includes username
,email
, password
and etc.However,to make changes usingemail
instead of username
you will need to customize this User
model.
- Why Customize the User Model?. Customizing the user model allows you to:
- Use email as the login field instead of username.
Add the extra field like
phone_number
orprofile_picture
.Implement Custom user roles and permissions.
- Steps to Customize the User Model.
Step 1 :Create a Custom Model
Django recommends using Custom user model at the beginning of your project to avoid complications later.Here's how to define a custom user model
:
Create the custom user model
in app's models.py
file .
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models
class UserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
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):
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):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=30, blank=True)
last_name = models.CharField(max_length=30, blank=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(auto_now_add=True)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name']
def __str__(self):
return self.email
In this example:
- The custom
User
model uses email as the unique identifier[USERNAME_FIELD]
-UserManager
is used to handle user creation.
Step2:Update settings.py
.
Tell django to update custom user model by adding this line to settings.py.
# settings.py
AUTH_USER_MODEL = 'yourapp.User'
Step3:Run migrations
Once the custom user model is defined and updated , you will need to make and apply migrations.
python3 manage.py makemigrations
python3 manage.py migrate
3.Create a Custom User manager.
- The
UserManager
class helps to manage user creation for both users and superusers. -
create_user
:Handles normal user creation with password hashing. -
create_superuser
: Handles superuser creations with necessary permissions.
You've already added UserManager
in User
model Above.
4.Customizing the Admin Panel for the User Model.
To manage users via admin interface in Django, you will need to register user model
and customize the admin
form.
# yourapp/admin.py
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import User
class CustomUserAdmin(UserAdmin):
model = User
list_display = ['email', 'first_name', 'last_name', 'is_staff']
search_fields = ['email', 'first_name', 'last_name']
ordering = ['email']
admin.site.register(User, CustomUserAdmin)
This register Custom user model
and adds it to admin interface.
5.Adding extra Fields to the User Model
You can easily extend custom user with extra fields.For example, you might want to add phone_number
and profile_picture
.
# yourapp/models.py
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
first_name = models.CharField(max_length=30, blank=True)
last_name = models.CharField(max_length=30, blank=True)
phone_number = models.CharField(max_length=15, blank=True, null=True)
profile_picture = models.ImageField(upload_to='profile_pics/', blank=True, null=True)
is_staff = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
date_joined = models.DateTimeField(auto_now_add=True)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = ['first_name', 'last_name']
Make sure to run migrations after adding new fields.
python manage.py makemigrations
python manage.py migrate
6.Customizing User authentication.
To log in users to use the email
instead of username
,create a custom authentication back-end:
# yourapp/backends.py
from django.contrib.auth.backends import BaseBackend
from .models import User
class EmailBackend(BaseBackend):
def authenticate(self, request, email=None, password=None):
try:
user = User.objects.get(email=email)
if user.check_password(password):
return user
except User.DoesNotExist:
return None
def get_user(self, user_id):
try:
return User.objects.get(pk=user_id)
except User.DoesNotExist:
return None
Then,update your settings.py
to use the authentication back-end:
settings.py
AUTHENTICATION_BACKENDS = ['yourapp.backends.EmailBackend']
**7.User Registration and Login-Views**
You can now create custom views for `user ``registration` and `login.` Here’s an example using Django REST Framework:
yourapp/views.py
from rest_framework import generics
from .models import User
from .serializers import UserSerializer
from rest_framework.permissions import AllowAny
class RegisterUserView(generics.CreateAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [AllowAny]
The corresponding `serializer` would look something like this:
yourapp/serializers.py
from rest_framework import serializers
from .models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ['email', 'first_name', 'last_name', 'password']
def create(self, validated_data):
user = User(
email=validated_data['email'],
first_name=validated_data['first_name'],
last_name=validated_data['last_name']
)
user.set_password(validated_data['password'])
user.save()
return user
**8. Testing and Validating Custom User Models**
Testing is critical to ensure everything works as expected. Create tests to verify `user ``registration` and authentication processes:
yourapp/tests.py
from django.test import TestCase
from .models import User
class UserTestCase(TestCase):
def setUp(self):
User.objects.create_user(email='testuser@example.com', password='password')
def test_user_creation(self):
user = User.objects.get(email='testuser@example.com')
self.assertEqual(user.email, 'testuser@example.com')
**9. Conclusion**
Customizing Django's user model offers flexibility to suit project-specific needs. By creating a custom user model, you can easily extend it, implement email-based authentication, and manage users more effectively.
Top comments (0)