Introduction
When you develop a web application with Django that requires account management, it is often necessary to customise the default “user” model provided by Django. In this article, we’ll discuss the important elements involved in creating a custom user model and an associated profile model.Why a custom user model?
Django provides a very comprehensive user template, but it may not meet all your needs. For example, you may want to add additional fields such as a profile photo or links to social networks. In these cases, we recommend creating a custom user template.Create a customised model for users
Assuming you already have the classic Django project code base, for example generated with the “django-admin startproject” command, we can add an app (a Django-specific concept) that we name users within the project with the :python manage.py startapp
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'users',
]
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager, PermissionsMixin
from django.db import models
# UserManager custom
class UserManager(BaseUserManager):
def create_user(self, email, password=None, **extra_fields):
...
# code pour créer un user
def create_superuser(self, email, password=None, **extra_fields):
...
# code pour créer un superuser
# User custom
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(unique=True)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
objects = UserManager()
USERNAME_FIELD = 'email'
REQUIRED_FIELDS = []
AUTH_USER_MODEL = 'users.User'
If in doubt about the value assigned to this parameter, remember that it is the application label (found in the users/apps.py file) followed by “.” followed by the name of the model, in this case the string “users.User”.
Create the profile template
To add additional information to the user account in the database, you can create a profile template. In fact, it’s even recommended. This template will be linked to the user template via a “1 to 1” relationship; to do this, you’ll use a OneToOneField. Here is an example of how to define a template called Profile for the user profile:class Profile(models.Model):
user = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
picture = models.ImageField(upload_to='profile_pics/')
bio = models.TextField()
def __str__(self):
return f"{self.user} profile"
Database migration
Don’t forget the essential step of generating the database migration code, using the :python manage.py makemigrations users
Migrations for 'users':
users/migrations/0001_initial.py
- Create model User
- Create model Profile
python manage.py migrate
Test the result
To test the result of adding these two models, we could complete the code for the UI part of the application, by writing a ‘view’, a ‘form’ and templates, as provided for in the Django framework. But to test things out straight away, we’re going to use the Django shell, via the following command:python manage.py shell
>>> from django.contrib.auth import get_user_model
>>> User = get_user_model()
>>> u = User(email="john.doe@example.com")
>>> u.save()
>>> from users.models import Profile
>>> u_profile = Profile(user=u)
>>> u_profile.save()
>>> print(f"{u} - {u_profile}")
john.doe@example.com - john.doe@example.com profile
from exampleapp.users.models import User
from django.contrib.auth import get_user_model
User = get_user_model()
def my_view(request):
users = User.objects.all()
...