9. Django DRF custom user 생성
일반 user model은 필드가 고정되어 있어 커스텀이 어렵다.
custom user model 생성 시 필드들을 자유롭게 커스텀 가능하다.
user model 만들기
# user/models.py
from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
# Create your models here.
class User(AbstractBaseUser):
username = models.CharField("사용자 계정", max_length=50, unique=True)
password = models.CharField("비밀번호", max_length=200)
email = models.EmailField("이메일 주소", max_length=100)
fullname = models.CharField("이름", max_length=20)
join_date = models.DateField("가입일", auto_now_add=True)
이후 settings.py에서 custom user를 선언해줘야하는데
AUTH_USER_MODEL을 찾아보면
global_settings.py에서 다음과 같이 작성되어 있는걸 볼 수 있다. 이는 선언이 되지 않을때의 기본 Django 셋팅이다.
custom user Django에 선언
고로 settings.py에서 선언을 해준다.
AUTH_USER_MODEL = 'user.User'
이후 runserver를 하면
AttributeError: type object 'User' has no attribute 'USERNAME_FIELD'
다음과 같은 에러가 나올것이다.
USERNAME_FIELD는 무엇을 ID로 사용할지 물어보는 것이다.
지금은 username으로 할거니 선언을 해주자.
from ntpath import join
from django.db import models
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
# Create your models here.
class User(AbstractBaseUser):
username = models.CharField("사용자 계정", max_length=50, unique=True)
password = models.CharField("비밀번호", max_length=200)
email = models.EmailField("이메일 주소", max_length=100)
fullname = models.CharField("이름", max_length=20)
join_date = models.DateField("가입일", auto_now_add=True)
USERNAME_FIELD = 'username'
#만약 email로 할꺼면 username을 주석(삭제)시키고
#USERNAME_FIELD = 'email'
이후 작업
REQUIRED_FIELDS를 선언해줄건데 이는 createsuperuser에 필요한 정보를(사실 저기에 필요하다는건 다른 user가 가입할때도 필요하다는거다) 제한해줄것이다.
#username, password는 기본 옵션이다.
REQUIRED_FIELDS = ['email', 'fullname']
그러나 귀찬하지니 공백으로 두자.(꼭 선언은 해줘야한다!)
다음
is_active = models.BooleanField(default=True)
is_admin = models.BooleanField(default=False)
으로 로그인 되었는지, admin인지 확인해주는 코드를 생성하고
하단의 권한 설정 코드를 만드는데 둘다 손댈 필요가 없다. 이유는 admin일 경우 항상 true, 비활성 사용자(is_active=False)일 경우 항상 false가 들어가기 때문이다. 선언만 해주자.
#권한 설정 #손 건들일이 없다
def has_perm(self, perm, obj=None):
return True
#손 건들일이 없다
def has_module_perms(self, app_label):
return True
마지막으로 objects = UserManager()를 선언해줄것인데 이는 User의 객체가 무엇이 될지를 의미한다.
UserManger 생성
class UserManager(BaseUserManager):
def create_user(self, username, password=None):
if not username:
raise ValueError('Users must have an username')
user = self.model(
username=username,
)
user.set_password(password)
user.save(using=self._db)
return user
def create_superuser(self, username, password=None):
user = self.create_user(
username=username,
password=password
)
user.is_admin = True
user.save(using=self._db)
return user
create_superuser는 python manage.py createsuperuser 실행시 들어가지는 함수이다.
완성본
#models.py
from django.contrib.auth.models import BaseUserManager, AbstractBaseUser
# custom user model 사용 시 UserManager 클래스와 create_user, create_superuser 함수가 정의되어 있어야 함
class UserManager(BaseUserManager):
def create_user(self, username, password=None):
if not username:
raise ValueError('Users must have an username')
user = self.model(
username=username,
)
user.set_password(password)
user.save(using=self._db)
return user
# python manage.py createsuperuser 사용 시 해당 함수가 사용됨
def create_superuser(self, username, password=None):
user = self.create_user(
username=username,
password=password
)
user.is_admin = True
user.save(using=self._db)
return user
class User(AbstractBaseUser):
#id는 겹치면 안되기 때문에 unique
username = models.CharField("사용자 계정", max_length=20, unique=True)
email = models.EmailField("이메일 주소", max_length=100)
#비밀번호 200인 이유, passing되서 들어가기 때문
password = models.CharField("비밀번호", max_length=200)
fullname = models.CharField("이름", max_length=20)
join_date = models.DateTimeField("가입일", auto_now_add=True)
# is_active가 False일 경우 계정이 비활성화됨
is_active = models.BooleanField(default=True)
# is_staff에서 해당 값 사용
is_admin = models.BooleanField(default=False)
# id로 사용 할 필드 지정.
# 로그인 시 USERNAME_FIELD에 설정 된 필드와 password가 사용된다.
USERNAME_FIELD = 'username'
# user를 생성할 때 입력받은 필드 지정
REQUIRED_FIELDS = []
objects = UserManager() # custom user 생성 시 필요
def __str__(self):
return self.username
# 로그인 사용자의 특정 테이블의 crud 권한을 설정, perm table의 crud 권한이 들어간다.
# admin일 경우 항상 True, 비활성 사용자(is_active=False)의 경우 항상 False
def has_perm(self, perm, obj=None):
return True
# 로그인 사용자의 특정 app에 접근 가능 여부를 설정, app_label에는 app 이름이 들어간다.
# admin일 경우 항상 True, 비활성 사용자(is_active=False)의 경우 항상 False
def has_module_perms(self, app_label):
return True
# admin 권한 설정
@property
def is_staff(self):
return self.is_admin