(회원가입 페이지 템플릿은 이미 작성했다고 가정한다)
장고에는 기본적으로 회원가입을 위한 폼이 내장되어 있다.(UserCreationForm) 그래서 view에서 함수로 회원가입 페이지를 렌더하면 아래와 같은 내장 폼을 볼 수 있다.
# 위 사진과는 관계 없는 코드
from django.contrib.auth.forms import UserCreationForm
def registerPage(request):
form=UserCreationForm()
context={'form':form}
return render(request, 'accounts/register.html', context)
회원가입 페이지를 띄우는 기본적인 view함수는 위와 같다. 하지만 이 내용만으로는 가입한 회원의 데이터가 저장되지 않는다. 따라서 내용을 추가하면 아래와 같다.
def registerPage(request):
form=UserCreationForm()
#---------추가한 내용 시작-------------
if request.method=="POST":
form=UserCreationForm(request.POST)
if form.is_valid():
form.save()
return redirect('login')
#---------추가한 내용 끝-------------
context={'form':form}
return render(request, 'accounts/register.html', context)
추가한 내용을 설명하면 html form에서 request방식이 POST이면, UserCreationForm 내용으로 POST한 내용을 넣는다. 그리고 그 내용이 유효하다면 폼을 저장하고, 다시 로그인 페이지로 보낸다.(원래는 메인페이지로 보내야 하지만 여기서는 일단 로그인 페이지로 보내겠다)
여기까지 설정하고 회원가입을 진행하면 admin 페이지에서 회원의 데이터가 저장된 것을 확인할 수 있다. (템플릿에도 폼을 가져오는 태그 를 추가해야 함)
장고에서 제공하는 기본 폼도 좋지만 항목이 username과 password(1,2)밖에 없어서 심심하다. 여기서 email 항목을 추가해보자.
폼에 항목을 추가하기 위해서는 forms.py에서 작업해야 한다. 또한 view에서 사용한 UserCreationForm과 사용자 관련 내장 모듈인 User 모듈, forms 모듈을 사용한다.
from django.contrib.auth.forms import UserCreationForm
# 장고의 유저 관련 내장 모델
from django.contrib.auth.models import User
from django import forms
class CreateUserForm(UserCreationForm):
class Meta:
model=User
fields=['username', 'email', 'password1', 'password2']
이름이 비슷해서 헷갈릴 수 있는데, CreateUserForm이 새로 만든 폼이다.(내장 폼인 UserCreationForm을 상속) 그리고 데이터를 저장하기 위해 model=User로 내장된 User모델을 지정했다. 마지막으로 사용할 필드로 username, email, password1, password2를 명시했다.
폼을 작성했으면 위에서 만든 view도 수정해 주어야 한다. 기존의 내장된 UserCreationForm을 그대로 사용하고 있기 때문.
# views.py
def registerPage(request):
#---------변경한 내용 시작-------------
form=CreateUserForm()
if request.method=="POST":
form=CreateUserForm(request.POST)
if form.is_valid():
form.save()
return redirect('login')
#---------변경한 내용 끝-------------
context={'form':form}
return render(request, 'accounts/register.html', context)
저장하고 회원가입 페이지를 들어가면 email 입력란이 생긴 것을 볼 수 있다.
(로그인 페이지 템플릿은 이미 작성했다고 가정한다.)
장고에는 로그인을 위한 내장 모듈도 존재한다. 로그인, 로그아웃 관련 view를 작성하기 위해서는 다음과 같은 모듈을 가져온다.
from django.contrib.auth import authenticate, login, logout
def loginPage(request):
if request.method=="POST":
username=request.POST.get('username')
password=request.POST.get('password')
user=authenticate(request, username=username, password=password)
if user is not None:
login(request, user)
return redirect('home')
context={}
return render(request, 'accounts/login.html', context)
작성한 함수를 설명하기 전에 모듈에 관한 간단한 설명을 덧붙이자면, authenticate 메소드는 기본적으로 username과 password를 키워드 인자 형식으로 받아 유저를 인증한다. 로그인을 위해서는 뷰에서 login 메소드를 사용해, 인증받은 유저만 로그인할 수 있도록 한다. 이 메소드는 유저의 아이디를 세션에 저장한다.
로그인 함수를 작성할 때 함수 이름을 login으로 하게 되면 메소드와 이름이 겹치므로 피해야 한다.
유저가 POST방식으로 요청을 보냈다면 유저가 입력한 아이디와 패스워드를 get으로 각각 저장한다. 저장한 아이디와 패스워드를 authenticate를 사용해 인증한 다음, 그 유저의 정보가 존재하는지 확인한다. 유저 정보가 확인되었다면 login 메소드에서 요청과 유저 정보를 인자로 받아 로그인을 처리한다.
authenticate를 사용한 로그인 뷰는 장고 공식문서에 따르면 낮은 수준의 인증 기능을 제공한다. 따라서 직접 인증 시스템을 만들어 쓸 것이 아니라면 장고에 내장된 LoginView를 사용하는 것이 바람직하다고 나와있으니 참고.
로그아웃은 로그인에 비하면 훨씬 간단하다.
def logoutUser(request):
logout(request)
return redirect('login')
로그인과 마찬가지로 함수명을 작성할 때는 logout으로 하면 메소드와 이름이 겹치므로 피하자.
기본적으로 요청을 인자로 받아 로그인 중인 유저를 로그아웃시킨다. 그리고 보관하고 있던 데이터도 모두 삭제한다.
로그인이 제대로 작동한다면, 그 다음에는 로그인 한 유저에게만 보여주고 싶은 페이지도 존재할 것이다. 일반적으로 이러한 기능을 위해서는 미들웨어를 사용하지만, 이번 글에서는 조금 더 간편하게 login decorator를 사용한다.
from django.contrib.auth.decorators import login_required
@login_required(login_url='login')
def products(request):
...
@login_required(login_url='login')
def customer(request, pk):
...
@login_required(login_url='login')
def createOrder(request, pk):
...
login_required라고 불리는 데코레이터를 사용하면, 로그인하지 않은 사람에게는 주소를 직접 입력하더라도 해당 페이지를 보여주지 않고, 설정한 login_url 페이지로 보낼 수 있다. 여기서는 로그인 페이지로 리디렉트 되도록 설정했다.