Menggunakan Email Sebagai Username pada Django 2

589

Ini digunakan pada proyek Django 2.x yang tidak memerlukan username, namun menggunakan email sebagai penggantinya. Dalam contoh ini, saya juga menghilangkan first name, last name, dan menambahkan full name.

Membuat Custom User Model berdasarkan AbstractUser

Saya menambahkan kode di bawah ini pada models.py pada app saya.

from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.translation import ugettext_lazy as _

class User(AbstractUser):
    username = None
    first_name = None
    last_name = None
    full_name = models.CharField(max_length=100)
    email = models.EmailField(_('email address'), unique=True)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = UserManager()

Perhatikan REQUIRED_FIELDS juga akan menyertakan USERNAME_FIELD secara otomatis. Ini nantinya berguna ketika membuat user menggunakan shell. Email harus bersifat unik.

Saya juga perlu memodifikasi UserManager untuk mengganti username dengan email. (Lihat objects = UserManager() di atas.) Kode di bawah ditambahkan pada models.py.

from django.contrib.auth.models import BaseUserManager

class UserManager(BaseUserManager):
    """
    Model manager untuk User tanpa 'username', 'first_name', dan 'last_name'.
    """

    use_in_migrations = True

    def _create_user(self, email, password, **extra_fields):
        """
        Membuat user dengan email dan password.
        """
        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):
        """Membuat user biasa."""
        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):
        """Membuat super user."""
        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)

Menggunakan Custom User Model Sebagai Default

Saya menambahkan variabel setting berikut pada settings.py.

AUTH_USER_MODEL = 'nama_app.User'

Melakukan Referensi pada Model

Jika saya ingin menggunakan User yang sudah dimodifikasi ini sebagai referensi, misalnya pada field ForeignKey, maka:

from django.conf import settings


class Device(models.Model):
    # ... field lainnya ...
    owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)

..Tidak lagi menggunakan auth.User atau django.contrib.auth.models.User.

Registrasi Custom User pada Django Admin

Langkah ini opsional. Saya juga dapat melakukan registrasi User buatan saya pada Django Admin. Perhatikan bahwa saya juga sudah mengganti first name dan last name dengan full name. Kode di bawah ini ada dalam admin.py pada app.

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

from .models import User


@admin.register(User)
class UserAdmin(DjangoUserAdmin):
    """Admin model untuk User tanpa field email."""

    fieldsets = (
        (None, {'fields': ('email', 'password')}),
        (_('Personal info'), {'fields': ('full_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', 'full_name', 'is_staff')
    search_fields = ('email', 'full_name')
    ordering = ('email',)

Referensi

  1. How to use email as username for Django authentication (removing the username)
  2. How to Extend Django User Model