출처: https://meyouus.tistory.com/64 [정보 공유 - For Me For You For Us]
본문으로 바로가기

※www.youtube.com/watch?v=tUqUdu0Sjyc&list=PL-51WBLyFTg2vW-_6XBoUpE7vpmoR3ztO&index=14

 

이 포스팅은 다음과 같은 youtube 영상을 따라하면서 배운 내용과 학습 내용을 담은 것이다:

  • Dennis Ivy - Filter Form Table Search | Django Framework (3.0) Crash Course Tutorials (pt 14)

현재 Django Version 3.1.2 를 쓰고 있다. Django는 파이썬을 쓰는 오픈소스 웹 프레임워크이다. 웹사이트 만들때 주로 쓰며, 간단한 것이 큰 특징이다.

 

 

※ Register(회원가입) / Login(로그인) / Logout(로그아웃) 구현하기

 

이번에는 Register, Login, 그리고 Logout을 구현을 해보는 것을 시도해보겠다

 

우선, reigster, login, logout html template과 urls.py에 추가를 해준다 (html template은 생략하도록 하고 중간중간에 필요할때 쓰겠다):

# urls.py
from django.urls import path
from . import views

urlpatterns = [
    ...
    path('register/', views.registerPage, name='register'),
    path('login/', views.loginPage, name='login'),
    path('logout/', views.logoutUser, name='logout'),

 

그리고 다음에는 forms.py에 다음을 추가해준다:

# forms.py
from django.contrib.auth.forms import UserCreationForm
from django import forms
from django.contrib.auth.models import User
...
class CreateUserForm(UserCreationForm):
	class Meta:
		model = User
		fields = ['username', 'email', 'password1', 'password2']

이는 우리가 login 페이지, register 페이지에서 구현해야 할 form들을 불러와주는 것인데, 본래의 Django UserCreationForm에는 email 추가란이 없다. 따라서 우리가 이를 덮어씌우기 위해서는 UserCreationForm을 상속받아 CreateUserForm이라는 새로운 class를 만들고 이를 쓰면된다.

 

UserCreationForm은 Django에서 제공하는 기본 회원가입 Form이라고 보면 된다. 이를 통해 회원가입, 로그인 등등을 구현할 수 있는데, 또한 우리는 이를 원하는 방식으로 변형시켜서 자신에게 알맞게 변형시키면 된다.

 

마지막으로는 views.pyloginPage, registerPage, logoutUser를 구현해준다:

# views.py
...
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import authenticate, login, logout
from django.contrib import messages
...
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)

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')
		else:
			messages.info(request, 'Username OR Password is Incorrect')
	context = {}
	return render(request, 'accounts/login.html', context)

def logoutUser(request):
	logout(request)
	return redirect('login')

registerPage를 살펴보면, form = CreateUserForm()으로, CreateUserFormform에 대입시키고, 이제 register 페이지에서 POST method가 불러일으키면, formCreateUserForm(request.POST)를 대입시키고, 만약 이 form이 옳바른 형식의 form이라면, 이 form 저장시키고 자동적으로 login 페이지로 불러주는 것이다.

 

loginPage의 경우, registerPage와 비슷한데, 여기서도 만약 login 페이지에서 POST method가 불러일으켜지면,

username = request.POST.get('username'), 그리고 password = request.POST.get('password')를 불러온 뒤,

userauthenticate(request, username=username, password=password)를 대입시킨다. 이때 이 authenticate은 불러온 POST에서 getusernamepassword가 서로 일치하고 알맞는지 확인하는 작업이다.

 

이때 if user is not None, 즉 같은 usernamepassword를 가진 user가 존재한다면, login(request, user)를 통해 user를 login 시키고, 바로 'home'으로 redirect 시킨다. 만약 user is None, 즉 존재하지 않거나 아이디 비밀번호가 틀렸을 경우, message를 불러일으키고 다른 template으로 바꾸지 않는다. 여기서 message에 대한 것은 여기에서 더 자세하게 볼 수 있다. 기회가 되면 message에 대한 것은 다음에 다루어 보도록 하겠다.

 

 

# login.html
<form method="POST" action=''>
	{% csrf_token %}
	Username: <input type="text" name="username">
	Password: <input type="password" name="password">
	<input type="submit" value="Login">
</form>

여기서 알아야 할 점은 login.html이 다음과 비슷하게 name="username", name="password" 이어야만 위의 username = request.POST.get('username'), password = request.POST.get('password')와 일치하여 맞게 할 수 있다. name이 달랐다면 그에 알맞게 바꿔주어야 한다.

 

logoutUser 같은 경우, 간단하다. login된 유저를 logout시키는 방식인데, login되어 있어야만 구현이 가능하므로, login이 되어 있지 않을때는 작동하지 않는다. 따로 template에 "{% url 'logout' %}"과 같은 기능을 자신의 웹사이트에 알맞게 추가하면 된다.

 

 

※ 로그인 되어 있지 않다면, 특정 페이지에 못 들어가게 구현하기

 

가끔씩 웹사이트에서 로그인이 되어 있지 않다면 그 페이지를 못보게 한다거나, 무슨 페이지를 들어가려고 했더니 로그인을 해야된다고 하면서 자동적으로 로그인 페이지로 넘어가는 것을 흔하게 겪었을 것이다. 이를 이번에 구현해보려고 한다.

 

이를 위해서는 views.py를 다음과 같이 추가해준다:

# views.py
from django.contrib.auth.decorators import login_required
...

decorator를 통해 login_required라는 함수를 불러왔다. 로그인이 되어 있지 않은 사람이 특정 함수/웹사이트를 불러오지 못하게 하기 위해서는 그 함수 바로 위헤 이 decorator를 넣으면 된다. 예를 들어, 우리는 로그인된 user가 아니라면 홈페이지 자체를 접근하는 것을 막고 싶다면:

# views.py
...
@login_required(login_url='login')
def home(request):
...

이런식으로 바로 위에 decorator를 삽입하면된다. 옆의 (login_url='login')의 경우, login_required를 통해 바로 login 페이지로 가게끔 설정해주는 것이다. 원하는 함수에 적용시키면 된다.

 

하지만 단점도 있다. 바로 원하는 모든 함수에 일일이 적용을 시켜줘야 한다. 보통은 middleware을 사용하여 적용을 시켜야하는데, 이는 다음에 더 공부하고 설명할 수 있도록 하겠다.

 

 

※ 로그인이 되어 있다면 로그인 페이지 / 회원가입 페이지에 못 들어가게 구현하기

 

보통 우리가 이미 로그인 되어 있을 때 회원가입 페이지를 들어가거나 로그인 페이지를 들어가려고 시도하지는 않는다. 물론 웹사이트가 우리에게 보여주지도 않지만, 우리가 시도를 할 경우에는 아예 접근이 안된다. 이번에는 그것을 한번 구현해보겠다.

 

views.py를 다음과 같이 바꾸어준다:

# views.py
...
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth import authenticate, login, logout
from django.contrib.auth.decorators import login_required
...
def registerPage(request):
	if request.user.is_authenticated:
		return redirect('home')
	else:
		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)

def loginPage(request):
	if request.user.is_authenticated:
		return redirect('home')
	else:
		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')
			else:
				messages.info(request, 'Username OR Password is Incorrect')
		context = {}
		return render(request, 'accounts/login.html', context)

registerPageloginPagerequest.user.is_authenticated가 새로 생겼단는 것을 볼 수 있다. 이는 간단하게 말해 "만약 이미 user가 authenticated, 즉 로그인이 되어 있는데 request가 들어왔으면" 이라는 뜻으로 해석하면 된다. 따라서 만약 이미 authenticated 된 상태에서 요청이 들어오면 바로 홈페이지로 redirect 시키면된다고 말해주고 있다.