Django 프레임워크에는 추상화된 User 모델과 인증 절차가 존재한다.
Django가 제공하는 기본적인 인증으로 충족되지 않는 요구사항이 있을 때 프로젝트에서 인증을 커스텀하기 위해 확장하거나 대체되어야 하는 필드들이 존재한다.
📝 JWT(Json Web Token)를 활용한 인증 절차를 구현해보기 위해
AbstractBaseUser, PermissionsMixin, BaseUserManager를 활용해보자

The easiest way to construct a compliant custom user model is to inherit from AbstractBaseUser. AbstractBaseUser provides the core implementation of a user model, including hashed passwords and tokenized password resets. You must then provide some key implementation details:
✅
AbstractBaseUser클래스는 비밀번호 설정에 대한 핵심 구현을 제공합니다.
class AbstractBaseUser(models.Model):
# 비밀번호
password = models.CharField(_("password"), max_length=128)
# 마지막 로그인 날짜
last_login = models.DateTimeField(_("last login"), blank=True, null=True)
# 활성화 여부
is_active = True
# 해당 부분에 Required로 담을 필드를 넣어줍니다.
REQUIRED_FIELDS = []
# Stores the raw password if set_password() is called so that it can
# be passed to password_changed() after the model is saved.
_password = None
...
✅ PermissionsMixin는 Django의 권한 프레임워크를 커스텀 유저에 쉽게 포함할 수 있도록 제공되는 추상 클래스입니다.
class PermissionsMixin(models.Model):
"""
Add the fields and methods necessary to support the Group and Permission
models using the ModelBackend.
"""
is_superuser = models.BooleanField(
_("superuser status"),
default=False,
help_text=_(
"Designates that this user has all permissions without "
"explicitly assigning them."
),
)
...
class Meta:
abstract = True
✅ BaseUserManager Custom 유저 모델을 위한 관리자도 정의해야합니다.
Writing a manager for a custom user model¶
You should also define a custom manager for your user model. If your user model defines username, email, is_staff, is_active, is_superuser, last_login, and date_joined fields the same as Django’s default user, you can install Django’s UserManager; however, if your user model defines different fields, you’ll need to define a custom manager that extends BaseUserManager providing two additional
커스텀 유저 모델에서 is_staff, is_active 등 Django의 기본 사용자 이외의 추가적인 필드를 정의하는 경우 BaseUserManager도 확장하여 아래 이미지 두 가지 추가 메서드(create_user, create_superuser)를 제공해주어야 합니다.

각 메서드는 사용자 이름 필드와 추가된 모든 필수 필드를 인수로 받아들여야 합니다.
Django Docs에서의 예시는 사용자이름 필드 -> Email Setting, 생년월일 필드가 Required이기 때문에 email, date_of_birth를 매개변수로 받는 것을 확인할 수 있습니다.
✅ objects, USERNAME_FIELD, REQUIRED_FIELDS 지정
BaseUserManager를 상속받아 확장한 Custom Manager를 확장 유저 모델의 objects로 할당하여 줍니다.
이를 통해 User 정보를 가져오는 ORM을 상용할 때 CustomUserManager가 사용됩니다.
USERNAME_FIELD는 유저를 식별하기 위한 고유한 값으로 들어가야 합니다.
class MyUser(AbstractBaseUser):
# unique=True
identifier = models.CharField(max_length=40, unique=True)
...
USERNAME_FIELD = "identifier"
로그인을 위해 username 특정 필드로 커스텀 할 수 있습니다.
USERNAME_FIELD 프로퍼티에 사용하고 싶은 필드를 적용해주시면 됩니다.
# 헬퍼 클래스 지정
objects = CustomUserManager()
# 사용자의 username field는 email으로 설정 (이메일로 로그인)
USERNAME_FIELD = 'email'
# 사용자의 username field는 phone으로 설정 (전화번호로 로그인)
USERNAME_FIELD = 'phone'
REQUIRED_FIEDLS에 필수값을 할당하면 django-admin createsuperuser 명령으로 user를 만들 때 Prompted와 상호 작용하기 위해 필요한 목록을 입력받을 수 있도록 지정해 줄 수 있습니다.
class MyUser(AbstractBaseUser):
...
date_of_birth = models.DateField()
height = models.FloatField()
...
REQUIRED_FIELDS = ["date_of_birth", "height"]
⚠️ USERNAME_FILED와 Password 필드는 항상 입력되도록 유도되기 때문에 포함되지 않아도 괜찮습니다.
✅ setting.py 설정
마지막으로 setting.py의 AUTH_USER_MODEL 설정을 사용하여 확장한 커스텀 유저 모델을 프로젝트의 기본 사용자 모델로 지정해줍니다.
# settings.py
# user 앱에서 내가 설정한 User를 사용하겠다고 설정.
AUTH_USER_MODEL = 'custom_user.CustomUser'
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, BaseUserManager
class CustomUserManager(BaseUserManager):
def create_user(self, email, password, **kwargs):
"""
주어진 이메일, 비밀번호 등 개인정보로 User 인스턴스 생성
"""
if not email:
raise ValueError('Users must have an email address')
user = self.model(
email=email,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, email=None, password=None, **extra_fields):
"""
주어진 이메일, 비밀번호 등 개인정보로 User 인스턴스 생성
단, 최상위 사용자이므로 권한을 부여
"""
superuser = self.create_user(
email=email,
password=password,
)
superuser.is_staff = True
superuser.is_superuser = True
superuser.save(using=self._db)
return superuser
# AbstractBaseUser를 상속해서 유저 커스텀
class CustomUser(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(
'Email',
max_length=60,
unique=True,
null=False,
blank=False,
help_text='Email Field'
)
is_active = models.BooleanField(
null=False,
blank=False,
default=True,
help_text='활성화 상태 여부입니다.'
)
is_staff = models.BooleanField(
null=False,
blank=False,
default=False,
help_text='Staff 여부입니다.'
)
created_at = models.DateTimeField(
null=False,
blank=False,
auto_now_add=True,
help_text='생성된 날짜입니다.'
)
updated_at = models.DateTimeField(
null=False,
blank=False,
auto_now=True,
help_text='업데이트 된 날짜입니다.'
)
# 헬퍼 클래스 사용
objects = CustomUserManager()
# 사용자의 username field는 email으로 설정 (이메일로 로그인)
USERNAME_FIELD = 'email'
def __str__(self):
return self.email
def get_short_name(self):
return self.email
#settings.py
AUTH_USER_MODEL = 'custom_user.CustomUser'