장고(Django) 핥짝 맛보기 - 사용자 인증을 참고
Auth 프레임워크
- 장고 admin 사이트에 접속할 때 생성했던 슈퍼유저가 장고에서 제공하는 Auth 프레임워크를 이용한다.
- Auth 프레임워크는 가입, 로그인, 로그아웃 세 가지의 기능을 제공한다.
- Auth 프레임워크의 User 모델을 확인해보자. 위치는 보통 가상환경의
Lib\site-packages\django\contrib\auth\models.py
에 있다. - 문서 장고 사용자 인증, django.contrib.auth 확인
class AbstractUser(AbstractBaseUser, PermissionsMixin):
"""
An abstract base class implementing a fully featured User model with
admin-compliant permissions.
Username and password are required. Other fields are optional.
"""
username_validator = UnicodeUsernameValidator()
username = models.CharField(
_('username'),
max_length=150,
unique=True,
help_text=_('Required. 150 characters or fewer. Letters, digits and @/./+/-/_ only.'),
validators=[username_validator],
error_messages={
'unique': _("A user with that username already exists."),
},
)
first_name = models.CharField(_('first name'), max_length=30, blank=True)
last_name = models.CharField(_('last name'), max_length=150, blank=True)
email = models.EmailField(_('email address'), blank=True)
is_staff = models.BooleanField(
_('staff status'),
default=False,
help_text=_('Designates whether the user can log into this admin site.'),
)
is_active = models.BooleanField(
_('active'),
default=True,
help_text=_(
'Designates whether this user should be treated as active. '
'Unselect this instead of deleting accounts.'
),
)
date_joined = models.DateTimeField(_('date joined'), default=timezone.now)
objects = UserManager()
EMAIL_FIELD = 'email'
USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['email']
class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
abstract = True # abstract 옵션이 True로 설정된 클래스는 makemigrations 커맨드 실행 시에 무시한다.
def clean(self):
super().clean()
self.email = self.__class__.objects.normalize_email(self.email)
def get_full_name(self):
"""
Return the first_name plus the last_name, with a space in between.
"""
full_name = '%s %s' % (self.first_name, self.last_name)
return full_name.strip()
def get_short_name(self):
"""Return the short name for the user."""
return self.first_name
def email_user(self, subject, message, from_email=None, **kwargs):
"""Send an email to this user."""
send_mail(subject, message, from_email, [self.email], **kwargs)
class User(AbstractUser):
"""
Users within the Django authentication system are represented by this
model.
Username and password are required. Other fields are optional.
"""
class Meta(AbstractUser.Meta):
swappable = 'AUTH_USER_MODEL'
- abstract 옵션이 True로 설정된 클래스는 makemigrations 커맨드 실행 시에 무시한다.
- Abstract 클래스는 보통 여러 개의 비슷한 클래스를 정의할 때 사용되는 데, Abstract 모델 클래스를 상속받은 클래스(서브클래스)는 상속받은 필드와 메소드는 정의할 필요는 없고 추가되는 필드와 메소드만 정의하면 된다.
- 즉, 여러 종류의 사용자 모델이 필요하다면 AbstractUser 클래스를 상속받아 사용하면 된다.
커스텀 사용자 모델
- AbstractUser 클래스를 사용하지 않고 새로 사용자 정보 모델을 정의해보자.
- 다른 프로젝트에서도 사용할 수 있게 별도의 앱으로 분리하자.
# user/models.py
from django.db import models
from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin, UserManager
class User(AbstractBaseUser, PermissionsMixin):
username = models.CharField('아이디', max_length=10, unique=True)
password = models.CharField('비밀번호', max_length=10)
email = models.EmailField('이메일', unique=True)
is_staff = models.BooleanField('스태프 권한', default=False)
is_active = models.BooleanField('사용여부', default=True)
created_at = models.DateTimeField('가입일', auto_now_add=True)
objects = UserManager()
USERNAME_FIELD = 'username' # 아이디를 사용자 식별자로 설정
REQUIRED_FIELDS = ['email'] # 필수입력값
- 장고에서 사용자 모델을 여러 앱에서 참조하고 있는 데, 현재 사용자 모델이 무엇인지 가리키는 AUTH_USER_MODEL 설정을 해주어야 한다.
# conf/settings.py
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'polls',
'board',
'user',
]
AUTH_USER_MODEL = 'user.User'
- migrate을 할 때 admin의 마이그레이션 파일이 user 앱의 0001_initial 마이그레이션 파일에 의존적이다는 오류가 뜬다. 이는 admin 사이트의 모델이 AUTH_USER_MODEL에 의존적이기 대문이다. admin 앱이 이미 마이그레이션 된 상태에서 커스텀 유저 모델을 마이그레이션을 하여니 문제가 된 것이다.
- admin 앱을 잠시 주석처리 한 후 다시 migrate를 하면 된다. 프로젝트 폴더의 settings.py의 admin 앱을 주석 처리, urls.py의 admin.site.urls도 주석 처리
- migrate가 되면 주석을 해제하고 다시 슈퍼유저 계정을 생성해주자.
python manage.py createsuperuser