Skip to content

Instantly share code, notes, and snippets.

@jacinator
Last active November 3, 2020 22:12
Show Gist options
  • Save jacinator/cbc0127e9807ea981a1daf35b7255cfb to your computer and use it in GitHub Desktop.
Save jacinator/cbc0127e9807ea981a1daf35b7255cfb to your computer and use it in GitHub Desktop.
This is the code needed to create a custom Django authentication system which trims out username and name fields an uses the email field for authentication.
from django.contrib import admin
from django.contrib.auth.admin import GroupAdmin, UserAdmin as BaseUserAdmin
from django.contrib.auth.models import Group as BaseGroup
from django.utils.translation import gettext_lazy as _
from .models import Group, User
admin.site.unregister(BaseGroup)
admin.site.register(Group, GroupAdmin)
@admin.register(User)
class UserAdmin(BaseUserAdmin):
list_display = ('email', 'id', 'is_active', 'is_confirmed', 'is_staff')
list_filter = ('is_staff', 'is_superuser', 'is_active', 'is_confirmed', 'groups')
ordering = ('email',)
search_fields = ('email',)
add_fieldsets = (
(None, {
'classes': ('wide',),
'fields': ('email', 'password1', 'password2'),
}),
)
fieldsets = (
(None, {
'fields': ('email', 'password'),
}),
(_('Permissions'), {
'fields': ('is_active', 'is_staff', 'is_superuser', 'is_confirmed', 'groups', 'user_permissions'),
}),
(_('Important Dates'), {
'fields': ('last_login', 'date_joined'),
}),
)
from django.contrib.auth.apps import AuthConfig
class UsersConfig(AuthConfig):
name = 'users'
from django.contrib.auth.base_user import AbstractBaseUser
from django.contrib.auth.hashers import make_password
from django.contrib.auth.models import (
Group as BaseGroup, PermissionsMixin, UserManager as BaseUserManager,
)
from django.core.mail import send_mail
from django.db import models
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _
class Group(BaseGroup):
# This class is only here as a proxy so that the group and custom user
# model display under the same app in the admin panel. When using the
# `Group` model elsewhere continue to import it from the Django contrib
# app.
class Meta:
proxy = True
verbose_name = _('group')
verbose_name_plural = _('groups')
class UserManager(BaseUserManager):
def _create_user(self, username, email, password, **extra_fields):
# Continue to accept `username` since the base definitions of
# `create_user` and `create_superuser` will still pass it in. The value
# of the parameter is overwritten and will always be `None`.
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.password = make_password(password)
user.save(using=self._db)
return user
# These two methods are only overwritten so that the `username` parameter
# can be excluded from the definition and pass `None` to the base
# definitions.
def create_superuser(self, email, password=None, **extra_fields):
return super().create_superuser(None, email, password, **extra_fields)
def create_user(self, email, password=None, **extra_fields):
return super().create_user(None, email, password, **extra_fields)
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
date_joined = models.DateTimeField(_('date joined'), default=now)
is_staff = models.BooleanField(_('staff status'), default=False, help_text=_(
'Designates whether the user can log into this admin site.'))
is_active = models.BooleanField(_('active'), default=True, help_text=_(
'Designates whether this user should be treated as active. Unselect '
'this instead of deleting accounts.'))
EMAIL_FIELD = USERNAME_FIELD = 'email'
objects = UserManager()
def email_user(self, subject, message, from_email=None, **kwargs):
send_mail(subject, message, from_email, [self.email], **kwargs)
class Meta:
ordering = ['-date_joined']
verbose_name = _('user')
verbose_name_plural = _('users')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment