Django/Django Rest Framework

9. Django DRF custom user 생성

S.T.Lee 2022. 6. 19. 01:30

일반 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