Custom User Model In Django 3
Tags: django, python, database
Published: 2020-10-31 15:07:00


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

```python 
#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

```

# Make Django Project

```python 
#your virtual env should be activated

django-admin startproject "project_name"
```
# 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

```
# Creating a Custom User Model
1. create a Custom Manager for User Model
2. create user Model

```python
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

```
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

```python
# 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.
```
# Registering Custom User Model to the Admin.

```python
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)

```
**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](http://127.0.0.1:8000/admin/) it will show you the email address field instead of the username field.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/lqmplk411557a9dj1uym.JPG)

after login, you will see the new user model.

![Alt Text](https://dev-to-uploads.s3.amazonaws.com/i/7h849g1gw26v3jbrrxld.JPG)

Now explore the NewUser Model admin interface.

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

Thank you.