개요
Django Project를 처음 생성하고 migrate를 시켰을 때 사용자 모델을 입맛대로 조정할 수 있는 방법이 없나 생각하게 되었습니다. 예를 들어 "userid 대신 email이나 phone을 userid로 로그인을 하려면 어떻게 해야 될까" 였는데 결론적으로 사용자 모델을 커스텀하기 위해선 AbstractUser와 AbstractBaseUser가 있다는 내용을 알게 되었습니다.
Django에서 제공하는 User Custom Model
AbstractUser Model
이 Model을 상속받아 쓰게 되면 password, last_login, username, fist_name, last_name, email 등의 DB Column을 생성합니다.
AbstractBaseUser Model
이 Model을 상속받아 쓰게 되면 password, last_login의 DB Column 기본적으로 사용하게 됩니다. 저는 입맛대로 필드를 추가하기 위해서 이 Model을 상속받아 사용하기로 결정했습니다.
어떻게 써볼까?
우선 AbstactBaseUser Model를 사용해서 유저의 역할(Role)을 구분하는 필드를 추가해보고 유저의 역할별로 다른 기능을 제공하는 형태의 모습을 생각해봤습니다. 이렇게 하는 이유는 django 체계에서는 사용자를 관리하기 위한 테이블을 하나밖에 사용할 수 없기 때문입니다.
AbstractBaseUser Model 사용하기
AbstractBaseUserModel Usage
from django.db import models
from django.contrib.auth.models import (
AbstractBaseUser,
PermissionsMixin
)
ROLE_TYPE = (
('1', 'Low'),
('2', 'Middle'),
('3', 'High')
)
class MyUser(AbstractBaseUser, PermissionsMixin):
class Meta:
db_table = "user"
# 사용자의 Role(역할)을 지정
role = models.CharField(
max_length=10,
choices=ROLE_TYPE,
default='Low',
verbose_name="사용자 타입"
)
# 사용자 이름
username = models.CharField(
max_length=10,
unique=True,
verbose_name="username"
)
# 가입일
date_joined = models.DateTimeField(auto_now_add=True, editable=False)
is_active = models.BooleanField(default=True)
is_staff = models.BooleanField(default=False)
USERNAME_FIELD = 'username'
# createsuperuser를 통해 생성할 때 입력받는 값 지정
REQUIRED_FIELDS = []
다음으로는 유저를 생성할 때와 관리자를 생성할 때 처리하는 부분을 위해 BaseUserManager를 객체를 상속해서 하나의 헬퍼 클래스를 만들어야 합니다.
BaseUserManager를 상속받은 헬퍼 클래스
from django.db import models
from django.contrib.auth.models import (
AbstractBaseUser,
BaseUserManager, # 추가
PermissionsMixin
)
class UserManager(BaseUserManager):
def create_user(self, username, password, **extra_fields):
user = self.model(
username=username,
password=password,
)
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, password, **extra_fields):
user = self.create_user(
username=username,
password=password,
**extra_fields
)
user.is_admin = True
user.is_superuser = True
user.is_staff = True
user.save(using=self._db)
return user
앞서 언급했듯 BaseUserManger를 상속받아 만든 UserManager 클래스는 두 가지 작업을 위한 메서드를 정의해야 됩니다.
- 일반 유저 생성에 관련 -> create_user
- 관리자 생성(admin 페이지 접근권한) - create_superuser
일반 유저를 생성할 때 동작하는 create_user() 메서드는 username과 passsword를 받아 저장하며 is_staff, is_superuser를 False로 세팅하면서 django admin 페이지에 접근을 못하게 막습니다. 슈퍼 유저를 생성할 때 동작하는 create_superuser() 메서드는 일반 유저와 같은 동작을 하지만 is_admin, is_staff, is_superuser를 True로 설정해 더 많은 권한을 할당하고 있습니다.
위와 같이 Manager를 만들었으며 잊지 말고 해당 모델에 이 Manager를 사용하기 위해 연결시켜 줍시다.
class MyUser(AbstractBaseUser, PermissionsMixin):
...
objects = UserManager()
Django에 알려주기
AbstractBaseUser Model을 사용하게 되면 Django에 유저 모델의 위치를 알려줘야 합니다. 아래와 같이 Django 프로젝트를 생성하고 나면 생기는 프로젝트 이름과 똑같은 폴더의 settings.py에 아래와 같이 설정합시다.
# django-project/settings.py
AUTH_USER_MODEL = "app_name.MODEL_NAME"
app_name 은 말 그대로 커스텀 유저 모델이 들어있는 app의 이름을 적어주고 MODEL_NAME에는 커스텀 유저 모델의 클래스 이름을 적어줍시다. 예를 들어 app_name이 custom이고 class 이름이 위에서 적은 MyUser 일 때 다음과 같이 적으면 됩니다
# django-project/settings.py
AUTH_USER_MODEL = "custom.MyUser"
언제 사용하면 좋을까?
AbstracBaseUser Model은 앞서 언급했듯 사용자에 관련된 정보를 커스텀해서 다루게 될 때 사용하면 좋습니다. 하지만 Project 중간에 AbstractBaseUser Model을 도입하기 힘들다는 단점이 있습니다. 그러니 사용자에 관련된 요구사항이 어느 정도 파악될 시점에서 사용하면 좋을 듯합니다.
'Frame Work > Django' 카테고리의 다른 글
django.db.utils.DataError: (1366, "Incorrect string value: ~~~) (0) | 2021.04.28 |
---|---|
django.db.utils.OperationalError: (1060, "Duplicate column name) (0) | 2021.04.27 |
setting.AUTH_USER_MODEL Error (0) | 2021.04.17 |
Django에 Unittest 적용해보기 (0) | 2021.04.04 |
django.db.utils.ProgrammingError: (1146, "Table 'app.auth_user' doesn't exist") (0) | 2021.03.28 |