DEV Community 👩‍💻👨‍💻

Justin Ndwiga
Justin Ndwiga

Posted on

Create a Custom User Model in Django

In this article, we will be learning how to create a custom user model in Django. Why do you need a custom user while Django has it's own auth models? Well, the default user class doesn't offer adequate fields that may fully describe a user based on the type of application you're building. For instance, you may want to add the full name, gender, location, etc. Worry not since even with all that abstraction that comes with Django we can still be able to tweak a couple of things. Let's get to it.

Let's Build

I am assuming you've already created a Django app and configured the database. I will be using Django 3.0.1 and Postgres 12.1. First, since the user model overrides the default user we need to define a custom UserManager class that extends BaseUserManager. We also have to ensure the class defines two methods; create_user and create_superuser methods. Create the user manager file under your startapp folder. Mine is in the path src/authentication/user_manager.py. Below is my project directory structure:
Alt Text

user_manager.py

"""User manager model module"""
from django.contrib.auth.models import BaseUserManager


class UserManager(BaseUserManager):
    """ 
    custom user model
    """
    def create_user(
            self,
            email,
            password,
            is_active=False,
            is_staff=False,
            is_admin=False
        ):
        """Create user."""
        if not email:
            raise ValueError('Users must have an email address')
        user = self.model(email=self.normalize_email(email))
        user.is_active=is_active
        user.is_staff=is_staff
        user.is_admin=is_admin
        user.set_password(password)
        user.save(using=self._db)
        return user

    def create_superuser(self, email, password):
        """Create a superuser."""
        return self.create_user(
            email,
            password,
            is_active=True,
            is_staff=True,
            is_admin=True
        )

For the user to have superuser permissions like site administration, you have to add is_superuser=True or have the has_perm class method in your user model that references the admin field. In this case, we're going with the latter.

Create a User model in the models file as below. Feel free to add any other fields as deemed necessary.

models.py

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin
from authentication.user_manager import UserManager


class User(AbstractBaseUser, PermissionsMixin):
    """User model."""
    email = models.EmailField(unique=True, null=False)
    first_name = models.CharField(max_length=30, null=True)
    last_name = models.CharField(max_length=30, null=True)
    password = models.CharField(max_length=128, blank=True)
    date_joined = models.DateTimeField(auto_now_add=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True, null=True)
    is_active = models.BooleanField(default=False)
    is_admin = models.BooleanField(default=False)
    is_staff = models.BooleanField(default=False)

    objects = UserManager()
    #unique identifier
    USERNAME_FIELD = 'email' 
    # any required fields besides email and password
    REQUIRED_FIELDS = []

    def __str__(self):
        return f'{self.first_name} {self.last_name}'

    @property
    def is_superuser(self):
        return self.is_admin

    def has_perm(self, perm, obj=None):
        return self.is_admin

AbstractBaseUser: Allows us to create a completely new User model.
PermissionsMixin: It will add fields that are specific for objects that have permissions, like is_admin.

Now add {app_name}.User to your settings.py file:

AUTH_USER_MODEL = 'authentication.User'

Finally run the migrations. $ python manage.py makemigrations && python manage.py migrate

To be able to login to the admin dashboard we have to register our custom User model in Django admin sites. Open app_name/admin.py and add the code below.

"""Register models to django admin."""
from django.contrib import admin
from django.contrib.auth.models import Group

from authentication.models import User

# list other models here
MODELS = [] 

class UserAdmin(admin.ModelAdmin):
    """Customize user/admin view on djano admin."""

    search_fields = ('email', )
    list_display = ('email', 'is_admin')
    list_filter = ('is_active', 'is_admin')
    ordering = ('email', )


    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        ('Permissions', {'fields': ('is_admin','is_staff')}),
        ('Primary personal information', {
            'fields': ('first_name', 'last_name')}),
        ('Status', {'fields': ('is_active', )}),
    )


admin.site.register(User, UserAdmin)

for model in MODELS:
    admin.site.register(model)

To test the app start by creating a superuser:
Alt Text
Great! Now visit http://127.0.0.1:8000/admin/ to login.

Conclusion

That's all for this article. You should now be able to tweak your user model to fit your application needs. Remember to add any new models under MODELS list of the admin file. I hope you found it valuable and look out for more in the future!

Top comments (1)

Collapse
 
addictd profile image
addictd

password isnt hashed while saving user from admin

🌚 Browsing with dark mode makes you a better developer.

It's a scientific fact.