Django Specifing a custom User model


Example

Django's built-in User model is not always appropiate for some kinds of projects. On some sites it might make more sense to use an email address instead of a username for instance.

You can override the default User model adding your customized User model to the AUTH_USER_MODEL setting, in your projects settings file:

AUTH_USER_MODEL = 'myapp.MyUser'

Note that it's highly adviced to create the AUTH_USER_MODEL before creating any migrations or running manage.py migrate for the first time. Due to limitations of Django's synamic dependecy feature.

For example on your blog you might want other authors to be able to sign-in with an email address instead of the regular username, so we create a custom User model with an email address as USERNAME_FIELD:

from django.contrib.auth.models import AbstractBaseUser

class CustomUser(AbstractBaseUser):
     email = models.EmailField(unique=True)
     
     USERNAME_FIELD = 'email'

By inherinting the AbstractBaseUser we can construct a compliant User model. AbstractBaseUser provides the core implementation of a User model.

In order to let the Django manage.py createsuperuser command know which other fields al required we can specify a REQUIRED_FIELDS. This value has no effect in other parts of Django!

class CustomUser(AbstractBaseUser):
    ...
    first_name = models.CharField(max_length=254)
    last_name = models.CharField(max_length=254)
    ...
    REQUIRED_FIELDS = ['first_name', 'last_name']

To be compliant with other part of Django we still have to specify the value is_active, the functions get_full_name() and get_short_name():

class CustomUser(AbstractBaseUser):
    ...
    is_active = models.BooleanField(default=False)
    ...
    def get_full_name(self):
        full_name = "{0} {1}".format(self.first_name, self.last_name)
        return full_name.strip()

    def get_short_name(self):
        return self.first_name

You should also create a custom UserManager for your User model, which allows Django to use the create_user() and create_superuser() functions:

from django.contrib.auth.models import BaseUserManager

class CustomUserManager(BaseUserManager):
    def create_user(self, email, first_name, last_name, password=None):
        if not email:
            raise ValueError('Users must have an email address')

        user = self.model(
            email=self.normalize_email(email),
        )

        user.set_password(password)
        user.first_name = first_name
        user.last_name = last_name
        user.save(using=self._db)
        return user

    def create_superuser(self, email, first_name, last_name, password):
        user = self.create_user(
            email=email,
            first_name=first_name,
            last_name=last_name,
            password=password,
        )

        user.is_admin = True
        user.is_active = True
        user.save(using=self.db)
        return user