Snippets: Python: Django: Auth: Custom USERNAME_FIELD

20th August 2020 at 2:19pm
Snippets: Python: Django: Auth

Code snippets copied from Practical Django 2 and Channels 2. Related django documentation: Customizing authentication.

# main.models.py
from django.contrib.auth.models import (
    AbstractUser,
    BaseUserManager,
)

class UserManager(BaseUserManager):
    use_in_migrations = True
        
    def _create_user(self, email, password,**extra_fields):
        if not email:
            raise ValueError("The given email must be set")
        email = self.normalize_email(email)
        user = self.model(email=email, **extra_fields)
        user.set_password(password)
        user.save(using=self._db)
        return user
                
    def create_user(self, email, password=None, **extra_fields):
        extra_fields.setdefault("is_staff", False)
        extra_fields.setdefault("is_superuser", False)
        return self._create_user(email, password, **extra_fields)
                
    def create_superuser(self, email, password, **extra_fields):
        extra_fields.setdefault("is_staff", True)
        extra_fields.setdefault("is_superuser", True)
        if extra_fields.get("is_staff") is not True:
           raise ValueError(
               "Superuser must have is_staff=True."
           )
        if extra_fields.get("is_superuser") is not True:
            raise ValueError(
               "Superuser must have is_superuser=True."
           )
        return self._create_user(email, password, **extra_fields)
                
class User(AbstractUser):
    username = None
    email = models.EmailField('email address', unique=True)
    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []
    objects = UserManager()

Then add a configuration directive to settings.py:

AUTH_USER_MODEL = "main.User"

Add these codes to main/admin.py (copy and adapt from DjangoUserAdmin class):

from django.contrib.auth.admin import UserAdmin as DjangoUserAdmin
from django.utils.translation import gettext_lazy as _

@admin.register(models.User)
class UserAdmin(DjangoUserAdmin):
    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        (_('Personal info'), {'fields': ('first_name', 'last_name')}),
        (_('Permissions'), {
            'fields': ('is_active', 'is_staff', 'is_superuser', 'groups', 'user_permissions'),
        }),
        (_('Important dates'), {'fields': ('last_login', 'date_joined')}),
    )
    add_fieldsets = (
        (None, {
            'classes': ('wide',),
            'fields': ('email', 'password1', 'password2'),
        }),
    )
    list_display = ('email', 'first_name', 'last_name', 'is_staff')
    search_fields = ('first_name', 'last_name', 'email')
    ordering = ('email',)