How to create custom User model in Django
Tags: django, python
Published: 2021-05-23 05:05:54

We can't imagine a web app without a custom User model, so today I will show you how you can create a custom User model in Django which will override the default User model.
Here are the main features of this custom model -
- Login by email instead of username
- Add own fields like Date of birth, Address, Id etc.

Let's quickly set up a new Django-Project
``` python
python -m venv env
cd env/Scripts
./activate
cd ../..
pip install django
django-admin startproject custom_user_model
cd custom_user_model
python manage.py startapp custom
```
## Editing models.py

Import the necessary modules like  AbstractBaseUser, BaseUserManager, PermissionsMixin etc. 

```python
from django.contrib.auth.models import AbstractBaseUser,BaseUserManager,PermissionsMixin
from django.utils.translation import gettext_lazy as _
from django.db import models
```

I am going to create a model first and then its manager.

```python
class Account(AbstractBaseUser,PermissionsMixin):
    email         = models.EmailField(_('email address'),max_length=60,unique=True)
    username      = models.CharField(max_length=30,unique=True)
    first_name    = models.CharField(max_length=30,blank=True)
    last_name     = models.CharField(max_length=30,blank=True)
    date_of_birth = models.DateField(verbose_name='date of birth',null=True,blank=True)
    city          = models.CharField(max_length=50,blank=True)
    date_joined   = models.DateTimeField(verbose_name='date_joined',auto_now_add=True)
    last_login    = models.DateTimeField(verbose_name='last login',auto_now=True)
    is_admin      = models.BooleanField(default=False)
    is_active     = models.BooleanField(default=False)
    is_staff      = models.BooleanField(default=False)
    is_superuser  = models.BooleanField(default=False)

    objects = AccountManager()
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username','first_name']

    def __str__(self):
        return self.email
```

Now create a Manager, here's the code for it 

```python
class AccountManager(BaseUserManager):
    def create_user(self,email,username,first_name,password,**other_fields):
        if not email:
            raise ValueError(_("Users must have an email address"))
        if not username:
            raise ValueError(_("Users must have an unique username"))
        email=self.normalize_email(email)
        user=self.model(email=email,username=username,first_name=first_name,**other_fields)
        user.set_password(password)
        user.save()
    
    def create_superuser(self,email,username,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('is_staff is set to False')
            if other_fields.get('is_superuser') is not True:
                raise ValueError('is_superuser is set to False')
            return self.create_user(email,username,first_name,password,**other_fields)
```

Our Models is ready but for see it we have to customize the admin.py file

## Editing admin.py 

Import the Account model and all other necessary modules and register the model at admin.site

```python
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .models import Account 
# Register your models here.

class UserAdminConfig(UserAdmin):
    list_display=['email','username','first_name','date_of_birth','city']
    search_fields=['email','username','city']
    readonly_fields=['date_joined','last_login']
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Personal info', {'fields': ('username','first_name','last_name','date_of_birth','city')}),
        ('Activity', {'fields': ('date_joined','last_login')}),
        ('Permissions', {'fields': ('is_admin','is_active','is_staff','is_superuser')}),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email','first_name', 'date_of_birth','city', 'password1', 'password2'),
        }),
    )

admin.site.register(Account,UserAdminConfig)
```

So our Custom User Model is ready to use or test.
![Done](https://media.giphy.com/media/RkDX47fpp2nHlaZdjY/giphy.gif)

If you just want to add some extra field to User model then you can just extend the User model by the OneToOne relationship which I will talk in the next post. 

Here is the full code at Github, You will find models.py and admin.py in a custom folder which we have discussed above.

{% github kritebh/custom-user-model-django no-readme %}