Django CBV 프로젝트 3. 사용자 인증 (회원가입)

참고 사이트

구조

# APP
user/
├── __init__.py      # 앱 패키지 초기화 스크립트입니다.
├── admin.py         # 장고 어드민 설정파일입니다. 어드민에 등록된 모델은 장고에서 자동 생성하는 어드민 페이지에서 관리할 수 있습니다.
├── apps.py          # 앱 설정 파일입니다.
└── migrations/      # 데이터베이스 마이그레이션 디렉토리. 장고 ORM은 모델 스키마의 변화가 생길 때마다 migration 파일을 생성하고 이것을 통해 스키마를 업데이트 합니다. migration 파일을 통해 협업자들과 함께 데이터베이스의 스키마를 동기화할 수 있습니다.
    ├── __init__.py  # 마이그레이션 패키지 초기화 스크립트입니다.
    ├── models.py        # 앱 모델 파일입니다. 회원의 모든 데이터를 저장할 데이터베이스를 장고 ORM을 통해 모델화합니다.
    ├── tests.py         # 앱 내의 기능들을 테스트하는 기능을 구현하는 파일입니다.
    ├── views.py         # 앱의 화면(template)과 데이터(model) 사이에서 사용자의 요청을 처리하여 모델에 저장하고, 모델에 저장된 데이터를 화면에 전달하는 역할을 합니다.
    ├── mixins.py        # 기본 메소드(인증보내기)를 지정해서 코드를 단순화 합니다.
    ├── validators.py    # 객체를 검증할 수 있는 기능을 제공 합니다.           
    ├── forms.py         # 앱의 form의 인자와 화면단을 구성해주는 파일입니다.
    └── templates/user/
            ├── login_form.html                # 로그인 form html
            ├── resend_verify_email.html       # 재 인증 메일 form html       
            ├── user_form.html                 # 회원가입 form html
            └── /email
                └── registration_verification.html      # 사용자 email 보낼 때 form html

장고 auth 프레임워크?

가입, 로그인, 로그아웃 지원

사용자 인증

  1. 사용자정보를 데이터베이스에 저장
  2. 저장된 데이터를 구분할 수 있는 유일한(누구와도 중복되지 않는) 키(key)를 지정해서 사용자를 식별(구별)
  3. 비밀번호 암호화 (해싱함수 / 암호화)

cf) 암호화와 해시
공통점 - 원래의 텍스트(평문)을 알아볼 수 없는 텍스트(암호문)으로 변경시켜줍니다.
차이점 - 암호화는 암호문에서 평문으로 되돌릴 수 있지만 해시는 되돌릴 수 없습니다.
암호 알고리즘의 종류 - des, aes, seed, rsa
해시 알고리즘의 종류 - md5, sha1, sha256, sha256

user App 생성

1
python manage.py startapp user

settings.py

1
2
3
4
5
6
INSTALLED_APPS = [
'django.contrib.auth', # auth 프레임워크
# --------- #
'bbs', # 게시판 app
'user', # user 정보 app
]

cf) DB가 잘못 되었을 때 데이터 삭제

1
2
find . -path "*/migrations/*.py" -not -name "__init__.py" -delete
# + db.splite3 파일삭제

회원 정보 모델 설계 (models.py)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
from django.contrib.auth.models import (
AbstractBaseUser, PermissionsMixin, UserManager
)
from django.contrib.auth.base_user import AbstractBaseUser, BaseUserManager
from django.contrib.auth.models import PermissionsMixin
from django.core.mail import send_mail
from django.db import models
from django.utils import timezone
from django.utils.translation import ugettext_lazy as _

class UserManager(BaseUserManager):
use_in_migrations = True

def _create_user(self, email, password, **extra_fields):
if not email:
raise ValueError('The given email must be set')
email = self.normalize_email(email)
user = self.model(email=email, **extra_fields)
user.set_password(password)
user.save(using=self._db)
return user

def create_user(self, email=None, password=None, **extra_fields):
extra_fields.setdefault('is_staff', False)
extra_fields.setdefault('is_superuser', False)
return self._create_user(email, password, **extra_fields)

def create_superuser(self, email, password, **extra_fields):
extra_fields.setdefault('is_staff', True)
extra_fields.setdefault('is_superuser', True)

if extra_fields.get('is_staff') is not True:
raise ValueError('Superuser must have is_staff=True.')
if extra_fields.get('is_superuser') is not True:
raise ValueError('Superuser must have is_superuser=True.')

return self._create_user(email, password, **extra_fields)

class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField('email', unique=True)
name = models.CharField('이름', max_length=30, blank=True)
is_staff = models.BooleanField('스태프 권한', default=False)
is_active = models.BooleanField('사용중', default=True)
date_joined = models.DateTimeField('가입일', default=timezone.now)

objects = UserManager()

USERNAME_FIELD = 'email' # email을 사용자의 식별자로 설정
REQUIRED_FIELDS = ['name'] # 필수입력값

class Meta:
verbose_name = _('user')
verbose_name_plural = _('users')
swappable = 'AUTH_USER_MODEL'

def email_user(self, subject, message, from_email=None, **kwargs): # 이메일 발송 메소드
send_mail(subject, message, from_email, [self.email], **kwargs)

회원가입 폼을 지정(forms.py)

1
2
3
4
5
6
7
from django.contrib.auth import get_user_model
from django.contrib.auth.forms import UserCreationForm

class UserRegistrationForm(UserCreationForm):
class Meta:
model = get_user_model()
fields = ('email', 'name')

회원가입 Class 작성(views.py)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

from django.contrib.auth.forms import UserCreationForm
from django.views.generic import CreateView

from user.models import User

from user.forms import UserRegistrationForm


class UserRegistrationView(CreateView):
template_name = 'user_model.html'
model = User
form_class = UserRegistrationForm
success_url = '/article/' #회원가입을 성공한다면 이 url로 이동해라

회원가입 setting 설정 (settings.py)

1
2
3
4
5
6
7
8
9
10
11
12
AUTH_PASSWORD_VALIDATORS = [
{
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
'OPTION': {'user_attributes': ('email', 'name')},
#forms.py에서 email과 name만 지정했기 때문에
},

#생략


AUTH_USER_MODEL = 'user.User' # '앱label.모델명'

실행화면

하루를 기록하다