로그인한 방문자만 포스트를 작성할 수 있도록 만들기
Posted on 2021-08-25 by GKSRUDTN99
Django로 웹사이트 만들기
장고
테스트 코드 작성
# blog/tests.py
def test_create_post(self):
response = self.client.get('/blog/create_post/')
self.assertNotEqual(response.status_code, 200)
self.client.login(username='trump', password='somepassword')
response = self.client.get('/blog/create_post/')
self.assertEqual(response.status_code, 200)
soup = BeautifulSoup(response.content, 'html.parser')
self.assertEqual('Create Post - Blog', soup.title.text)
main_area = soup.find('div', id='main-area')
self.assertIn('Create New Post', main_area.text)
우선, 로그인 하지 않은 상태에서는 status_code가 200이 아니어야 한다.
로그인 하였다면, 기존과 같은 테스트를 진행하도록 한다.
로그인 테스트 유의사항
이전에 작성한 tests.py
에서는 유저를 다음과 같은 코드로 생성한다.
self.user_trump = User.objects.create(username='trump', password='somepassword')
위와 같은 방법으로 유저를 생성할 경우, password 필드에 somepassword
문자열이 그대로 들어가게 된다.
하지만, 위의 경우처럼 client.login
을 시도할 경우, password 필드에 somepassword
를 입력하면, 장고는 somepassword
를 해싱한 값을 DB와 비교한다.
하지만, DB에는 해싱된 값이 아닌 somepassword
문자열이 그대로 들어가 있으므로, 로그인이 정상적으로 동작하지 않는다.
위 문제를 해결하기 위해, 유저 생성 코드를 다음과 같이 수정한다.
self.user_trump = User.objects.create(username='trump')
self.user_trump.set_password('somepassword')
self.user_trump.save()
PostCreate 클래스에 LoginRequiredMixin 추가하기
PostCreate클래스에 매개변수로 LoginRequiredMixin 클래스를 추가하면 로그인했을 때만 정상적으로 페이지가 보이게 된다.
✔︎ Mixin은 확장하는 클래스 전에 적는다!
# blog/views.py
from django.shortcuts import render
from django.views.generic import ListView, DetailView, CreateView
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Post, Category, Tag
(...생략...)
class PostCreate(LoginRequiredMixin, CreateView):
model = Post
fields = ['title', 'hook_text', 'content', 'head_image', 'file_upload', 'category']
테스트 코드 추가
테스트 코드에 포스트를 작성한 후 submit 버튼을 클릭하는 행위까지 구현한다.
# blog/tests.py
def test_create_post(self):
# 로그인 하지 않으면 status code가 200이면 안된다!
response = self.client.get('/blog/create_post/')
self.assertNotEqual(response.status_code, 200)
# 로그인을 한다.
self.client.login(username='trump', password='somepassword')
response = self.client.get('/blog/create_post/')
self.assertEqual(response.status_code, 200)
soup = BeautifulSoup(response.content, 'html.parser')
self.assertEqual('Create Post - Blog', soup.title.text)
main_area = soup.find('div', id='main-area')
self.assertIn('Create New Post', main_area.text)
self.client.post(
'/blog/create_post/',
{
'title': 'Post form 만들기',
'content': "Post Form 페이지를 만듭시다.",
}
)
last_post = Post.objects.last()
self.assertEqual(last_post.title, "Post form 만들기")
self.assertEqual(last_post.author.username, 'trump')
self.client.post()
함수는 첫 번째 인수인 경로로 두 번째 인수인 딕셔너리 정보를 POST 방식으로 보낸다.
자동으로 author 필드 채우기
CreateView
클래스에는 form_valid()
함수가 정의되어 있다.
사용자가 내용을 입력한 뒤 전송하면 form_valid()
함수가 호출된다.
form_valid()
함수는 사용자가 폼에 담아 보낸 유효한 정보를 사용해 포스트를 만들고, 이 포스트를 고유 경로로 보내주는(redirect) 역할을 한다.
# blog/views.py
from django.shortcuts import render, redirect
from django.views.generic import ListView, DetailView, CreateView
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import Post, Category, Tag
(... 생략 ...)
class PostCreate(LoginRequiredMixin, CreateView):
model = Post
fields = ['title', 'hook_text', 'content', 'head_image', 'file_upload', 'category']
def form_valid(self, form):
current_user = self.request.user
if current_user.is_authenticated:
form.instance.author = current_user
return super(PostCreate, self).form_valid(form)
else:
return redirect('/blog/')