DEV Community

Cover image for Custom User Model In Django 3
Sachin Chaurasiya
Sachin Chaurasiya

Posted on • Edited on

Custom User Model In Django 3

In this post, we will see how we can define our own User Model and use it. and also what are the changes we have to make while registering Custom User Model.

Django Built-in User Model is Good for normal cases. but what if you want to add some extra fields like age, gender, etc.

Here Someone will say why can't we extend the Built-in User Model and make Profile Model for users. this is also a good choice but Django itself state that we should use the Custom User Model. Because it is the best approach when you are working on really big projects.

Install Django in the virtual environment

#we will use venv module to install Django

#navigate to your working directory and run the below command

python -m venv "vertual_environment_name"

#now activate the virtual environment

/venv/scripts/activate.bat 

# now Install Django

pip install django==3.0.8

Enter fullscreen mode Exit fullscreen mode

Make Django Project

#your virtual env should be activated

django-admin startproject "project_name"
Enter fullscreen mode Exit fullscreen mode

Make user app

#navigate to your project folder

python manage.py startapp "app_name"

python manage.py startapp users

#add users app to installed_apps in your settings.py file

Enter fullscreen mode Exit fullscreen mode

Creating a Custom User Model

  1. create a Custom Manager for User Model
  2. create user Model
from django.db import models
from django.utils import timezone
from django.utils.translation import gettext_lazy as _
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager

# 1. creating Custome Manager for User Model
class CustomAccountManager(BaseUserManager):
    def create_user(self, email, user_name, first_name, password, **other_fields):
        if not email:
            raise ValueError(_('You must provide an email address'))
        # convert all in lowercase
        email = self.normalize_email(email)
        user = self.model(email=email, user_name=user_name,
                          first_name=first_name, **other_fields)
        user.set_password(password)
        user.save()
        return user

    def create_superuser(self, email, user_name, first_name, password, **other_fields):
        other_fields.setdefault('is_staff', True)
        other_fields.setdefault('is_superuser', True)
        other_fields.setdefault('is_active', True)

        if other_fields.get('is_staff') is not True:
            raise ValueError('Superuser must be assigned to is_staff=True.')
        if other_fields.get('is_superuser') is not True:
            raise ValueError(
                'Superuser must be assigned to is_superuser=True.')
        return self.create_user(email, user_name, first_name, password, **other_fields)

# 2. Creating Custom User Model
class NewUser(AbstractBaseUser, PermissionsMixin):
    email = models.EmailField(_('email address'), unique=True)
    user_name = models.CharField(max_length=150, unique=True)
    first_name = models.CharField(max_length=150)
    start_date = models.DateTimeField(default=timezone.now)
    about = models.TextField(_('about'), max_length=500, blank=True)
    is_staff = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)

    objects = CustomAccountManager()

    USERNAME_FIELD = 'email'

    # required for superuser
    REQUIRED_FIELDS = ['user_name', 'first_name']

    def __str__(self):
        return self.user_name

Enter fullscreen mode Exit fullscreen mode

First, we created the Custom Manager for User model. (manager is used to querying the model and default is 'objects')

Django provide the BaseUserManager and by using this we created our own manager where we have defined two methods

  1. create_user
  2. create_superuser

there is only one major difference that is we are setting is_superuser and is_staff attribute to True in create_superuser() method.

and other codes needs no explanation it is just some exception checking and all.

Second, we have created the NewUser model by Extending AbstractBaseUser provided by Django. we have also used PermissionsMixin for some permission checks.

we have defined some fields like email, user_name, first_name, start_date, about, etc.

also, we have defined two Booleans attribute is_staff and is_active.

is_staff is set to False so that not every user get staff status.

is_active is set to True so that every user get activated by default.

objects = CustomAccountManager() is most important line. here we are setting our custom manager that we have defined earlier.

USERNAME_FIELD='email' this line tells that now the user will log in using its email instead of user_name.

REQUIRED_FIELDS = ['user_name', 'first_name'] this specify that when we create super_user it should get user_name and first_name otherwise it will raise and exception.

next, we have defined str() method so it will show user-friendly name in Django admin panel.

Add AUTH_USER_MODEL attribute in your settings.py file

# you must have added the users app into the installed_apps
# add this attribute

AUTH_USER_MODEL = 'users.NewUser'

# it will tell Django to use this as a User Authentication model.
Enter fullscreen mode Exit fullscreen mode

Registering Custom User Model to the Admin.

from django.contrib import admin
from .models import NewUser
from django.contrib.auth.admin import UserAdmin
from django.forms import Textarea


class UserAdminConfig(UserAdmin):
    model = NewUser
    search_fields = ('email', 'user_name', 'first_name',)
    list_filter = ('email', 'user_name', 'first_name',
                   'is_active', 'is_staff')
    ordering = ('-start_date',)
    list_display = ('email', 'user_name', 'first_name',
                    'is_active', 'is_staff')
    fieldsets = (
        (None, {'fields': ('email', 'user_name', 'first_name')}
         ), ('Permissions', {'fields': ('is_staff', 'is_active')}),
        ('Personal', {'fields': ('about',)}),
    )
    formfield_overrides = {
        NewUser.about: {'widget': Textarea(attrs={'rows': 10, 'cols': 40})},
    }
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'user_name', 'first_name', 'password1', 'password2', 'is_active', 'is_staff')
        }),
    )


admin.site.register(NewUser, UserAdminConfig)

Enter fullscreen mode Exit fullscreen mode

model = NewUser is telling Django to use NewUser as Model.

search_fields is used to add a search field in admin panel with specified fields.

ordering is used to define order field.

list_display is used to show specified field in the admin panel.

fieldsets is used to define what fieldset you want to show in your admin panel.

formfield_overrides is used to override the default field with specified field.

add_fieldsets is used to add fieldsets to the admin panel.

and at the end admin.site.register(NewUser, UserAdminConfig) registering the NewUser Model.

Now when you visit the Click Here it will show you the email address field instead of the username field.

Alt Text

after login, you will see the new user model.

Alt Text

Now explore the NewUser Model admin interface.

Comment down if you have any queries will try to solve as much as possible.

Thank you.

Top comments (0)