Custom User Model
Now, we are going to create a custom user model for our project.
Django comes with built-in user authentication system which has it's own user model. But most of the time, we need to create our custom user model to meet the requirements.
Therefore, in this project you will learn how to create a custom user model that meets our project requirements.
Resources
Code Setup
-
First of all, you need to download the project code files from this link: DOWNLOAD ZIP FILE
-
Now, extract the folder on the desktop.
-
Then, copy the mysite folder which is the project root directory.
-
Replace the mysite folder of your project with the copied mysite folder. So, if you made any mistake while writing the code in the previous section, then, it won't affect your learning in this section.
-
Open your project in the VS code and in the terminal, activate the virtual environment, and move to the mysite.
-
Now, here is a warning to you. Don't run the migration command. We will run the migration once we have completed creating the user model. In case, you have already ran the migration command then delete the sqlite database.
Media Files Configuration
Before creating the custom user model, we need to setup media files configuration settings. Because in the custom user model, we are going to create a ImageField to handle the profile image of user. Therefore, to deal with the images in django, we need to configure MEDIA_URL and MEDIA_ROOT.
- First of all, open settings.py file and add this code under STATIC_FILES Configuration settings.
MEDIA_URL = "media/"
MEDIA_ROOT = BASE_DIR / "media"
-
Media_URL is similar to the STATIC_URL. MEDIA_URL is basically a URL that serves the files in the 'media' directory.
-
MEDIA_ROOT is the absolute path to the directory where the Django will save our media files.
Now, we need to configure the urls path for media files. In the mysite/urls.py, add this code under static files url configuration.
# Media Files Configurations
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
Custom User Model
Now lets create our custom user model. Open the models.py file of user app and create a new User class.
class User():
This user class will not inherit models.Model but instead it will inherit AbstractBaseUser, PermissionsMixin.
We can import these required things from django.contrib.auth.models.
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
Now, inherit the AbstractBaseUser and PermissionsMixin in the user model.
class User(AbstractBaseUser, PermissionsMixin):
After that, let us add some model fields to meet our project requirements.
We need an email field to authenticate user with email address.
email = models.EmailField(max_length=320, unique=True)
Create a first_name model field to store first name of the user.
first_name = models.CharField(max_length=30, blank=True)
Create a middle_name model field to store the middle name of the user.
middle_name = models.CharField(max_length=30, null=True, blank=True)
Create a last_name model field to store the last name of the user.
last_name = models.CharField(max_length=30, blank=True)
Create date_of_birth model field to store the date_of_birth of the user.
date_of_birth = models.DateField(null=True, blank=True, help_text="Enter Date in this Format: Year-Month-Day")
Create gender field to store the information related to gender. In this field, we will give choices to the user to choose between male and female.
gender = models.CharField(max_length=1, choices=[("M", "Male"), ("F", "Female")], null=True)
The choices modeld file option take a list containing tuple which represents the choices.
Create a blood_group field to store the blood group of the user. In this field also, we will give choices to the user to choose the blood group. First of all, create a blood group choices above the User Model.
BLOOD_GROUP_CHOICES = [
("A+", "A+"),
("A-", "A-"),
("B+", "B+"),
("B-", "B-"),
("O+", "O+"),
("O-", "O-"),
("AB+", "AB+"),
("AB-", "AB-"),
]
Then create the blood group field.
blood_group = models.CharField(max_length=3, null=True, choices=BLOOD_GROUP_CHOICES)
Create identity document type field that store the document type which user will provide as an identity information. First create the choices identity_document_type.
DOCUMENT_CHOICES = [
("Voter Id", "Voter ID"),
("Passport", "Passport"),
("Citizenship Number", "Citizenship Number"),
]
Now, create the model field.
identity_document_type = models.CharField(max_length=32, null=True, choices=DOCUMENT_CHOICES)
Create a model field named identity_document_number to store the document number which the user will provide.
identity_document_number = models.CharField(max_length=32)
Create a image field that stores the profile image of the user.
photo = models.ImageField(verbose_name="Profile Picture", upload_to="profileImage/", null=True)
To work with image field, we need to install pillow in our virtual environment.
pip install pillow
Also update the project dependencies in the requirements.txt file. [Move to the reposiory root where requirements.txt file is present]
pip freeze > requirements.txt
Create a date_joined field to store the date and time when the user signups.
date_joined = models.DateTimeField(default=timezone.now)
Import the timezone from django.utils
from django.utils import timezone
Create a last_updated field to store the date and time when user updates their profile information.
last_updated = models.DateTimeField(auto_now=True)
Create an is_email_verified field that stores the boolean value about the email verification status of user.
is_email_verified = models.BooleanField("Email Verified", default=False)
Create is_active field that stores whether the user is active or not.
is_active = models.BooleanField('active', default=True)
Create is_staff field that stores the staff status of the user. You will learn more about is_staff field, later in this course.
is_staff = models.BooleanField('staff status', default=False)
Create is_superuser field that stores the superuser status of the user. You will learn about is_superuser field also, later in this course.
is_superuser = models.BooleanField('superuser status', default=False)
Now, we need to provide username field of the user model. If we set email as our username_field then we can log in user using email and password.
USERNAME_FIELD = 'email'
After that we need to set the required_fields. This field takes a list of model field that are required when user performs signup.
REQUIRED_FIELDS = ['first_name', 'last_name']
Now, we need to setup meta class for this user model. This step is optional but lets implement it because till now we haven't discussed about class Meta.
In Django, the Meta class is used to specify additional options for a model. The Meta class is defined within the model class and allows us to set additional (meta) options such as database table name, default ordering of the model, verbose name and verbose_name_plural.
class Meta:
verbose_name = 'user'
verbose_name_plural = 'users'
Finally, create one method that returns full_name of the user.
def get_full_name(self):
'''
Returns the full name of user
'''
return f"{self.first_name} {self.middle_name} {self.last_name}"
Creating a Model manager
When we were learning how to query the database in the django ORM section, I mentioned about model manager named "objects". In case you forgot about it, let me remind.
Model manager is the class through which all our database operations were provided. So, if you need to query all the data then we use all() method provided by objects which is the default model manager.
After creating a custom user model, we need to create a model manager.
Add the objects above Username_fields.
objects = UserManager()
Create a class above User model.
class UserManager()
This class will inherit BaseUserManager. So, import it.
from django.contrib.auth.base_user import BaseUserManager
Now, inherit it in the UserManager.
class UserManager(BaseUserManager):
Set use_in_migrations to true
use_in_migrations = True
In Django, the use_in_migrations option is used to specify whether a field should be included in database migrations or not.
Now, create an internal function named create_user. This function is intented to use within a module and are not meant to be a part of public API. So, use single underscore before the function name.
def _create_user(self, email, password, **extra_fields):
"""
Creates and saves a User with the given email and password.
"""
if not email:
raise ValueError('The given username must be set')
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user
Now add the create_user method.
def create_user(self, email, password=None, **extra_fields):
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)
After that add the create_superuser method to handle the values for superuser.
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_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')
return self._create_user(email, password, **extra_fields)
Admin Panel Integration
Before you register the model in django admin panel, we need to provide the location of our custom user model to the django.
In the settings.py file, add
AUTH_USER_MODEL = "user.User"
Now, in the user/admin.py file, first import the user model.
from django.contrib.auth import get_user_model
Then, get the instance of user model.
User = get_user_model()
Finally, register the user model.
admin.site.register(User)
Creating a Superuser Account
Before we run the migration, at first, delete the sqlite database if you have.
Now, run the migrations.
python manage.py makemigrations
python manage.py migrate
Then create a superuser
python manage.py createsuperuser
Open the admin panel and browse the user model page.