앞에서 질문 등록, 조회 기능을 만들었다. 이번에는 답변 등록과 답변을 보여주는 기능을 만들어 보자.
답변 저장하고 표시하기
(1단계) 질문 상세 템플릿에서 [답변등록] 버튼 만들기
질문 상세 템플릿 pybo/question_detail.html파일을 수정하자.
form 엘리먼트 안에 <textarea> , <input> 태그를 포함시켜 답변내용, 답변등록 버튼을 추가하자.
# D:\projects\mysite\templates\pybo\question_detail.html <h1>{{ question.subject }}</h1> <div> {{ question.content }} </div> <form action="{% url 'pybo:answer_create' question.id %}" method="post"> {% csrf_token %} <textarea name="content" id="content" rows="15"></textarea> <input type="submit" value="답변등록"> </form> |
[답변등록] 버튼을 클릭할 때 호출되는 URL은 action 속성에 있는 "{% url 'pybo:anser_create' question_id %}" 이다. 그리고 form 엘리먼트 바로 아래에 있는 {% csrf_token %} 코드는 보안 관련 항목이다. {% csrf_token %}는 form 엘리먼트를 통해 전송된 데이터(답변)가 실제로 웹 브라우저에서 작성된 데이터인지 판단하는 검사기 역할을 한다. 그러므로 <form>태그 바로 밑에 {% csrf_token %}를 항상 입력해야 한다. 해킹처럼 올바르지 않은 방법으로 데이터가 전송되면 서버에서 발행한 csrf_token값과 해커가 보낸 csrf_token값이 일치하지 않으므로 오류를 발생시켜 보안을 유지할 수 있다.
(2단계) 답변 등록을 위한 URL 매핑 등록하기
pybo/urls.py 파일에 답변 등록을 위한 URL 매핑을 등록하자.
# D:\projects\mysite\pybo\urls.py from django.urls import path from . import views app_name = 'pybo' urlpatterns = [ path('', views.index, name='index'), path('<int:question_id>/', views.detail, name='detail'), path('answer/create/<int:question_id>/', views.answer_create, name='answer_create') ] |
이 코드는 사용자가 상세 화면에서 [질문답변] 버튼을 클릭했을 때 작동할 form 엘리먼트의 /pybo/answer/create/4/에 대한 URL 매핑을 추가한 것이다.
(3단계) answer_create 함수 추가하기
form 엘리먼트에 입력된 값을 받아 데이터베이스에 저장할 수 있도록 answer_create 함수를 pybo/views.py파일에 추가하자.
# D:\projects\mysite\pybo\views.py from django.shortcuts import render, get_object_or_404 from .models import Question from django.utils import timezone # Create your views here. def index(request): question_list = Question.objects.order_by('-create_date') context = {'question_list': question_list} return render(request, 'pybo/question_list.html', context) def detail(request, question_id): question = get_object_or_404(Question, pk=question_id) context = {'question': question} return render(request, 'pybo/question_detail.html', context) # pybo 답변등록 def answer_create(request, question_id): question = get_object_or_404(Question, pk=question_id) # Answer 모델이 Question 모델을 FK로 참조하고 있으므로 question.answer_set.create 같은 표현을 사용할 수 있다. question.answer_set.create(content=request.POST.get('content'), create_date=timezone.now()) # Answer 모델로 Answer 모델 데이터를 저장하는 예 question = get_object_or_404(Question, pk=question_id) answer = Answer(question=question, content=request.POST.get('content'), create_date=timezone.now()) answer.save() |
answer_create 함수의 question_id 매개변수에는 URL 매핑 정보값이 넘어온다. request 매개변수에는 pybo/question_detail.html에서 textarea에 입력된 데이터가 파이썬 객체에 담겨 넘어온다. 이 값을 추출하기 위한 코드가 바로 request.POST.get('content')이다. 그리고 Question 모델을 통해 Answer 모델 데이터를 생성하기 위해 question.answer_set.create를 사용했다.
(4단계) 답변등록 후 상세 화면으로 이동하게 만들기 → redirect 함수
답변을 생성한 후 상세 화면을 호출하려면 redirect 함수를 사용하여 코드를 작성하면 된다. redirect 함수는 함수에 전달된 값을 참고하여 페이지 이동을 수행한다. redirect 함수의 첫번째 인수에는 이동할 페이지의 별칭을, 두 번째 인수에는 해당 URL에 전달해야 하는 값을 입력한다.
# D:\projects\mysite\pybo\views.py from django.shortcuts import render, get_object_or_404, redirect from .models import Question from django.utils import timezone # Create your views here. def index(request): question_list = Question.objects.order_by('-create_date') context = {'question_list': question_list} return render(request, 'pybo/question_list.html', context) def detail(request, question_id): question = get_object_or_404(Question, pk=question_id) context = {'question': question} return render(request, 'pybo/question_detail.html', context) # pybo 답변등록 def answer_create(request, question_id): question = get_object_or_404(Question, pk=question_id) question.answer_set.create(content=request.POST.get('content'), create_date=timezone.now()) return redirect('pybo:detail', question_id=question_id) |
질문 상세 페이지에 다시 접속해 보자. 그러면 다음처럼 답변을 등록할 수 있는 창과 [답변등록] 버튼이 보인다.
http://127.0.0.1:8000/pybo/4/
(5단계) 등록된 답변 표시하기
질문 상세 화면에 답변을 표시하려면 pybo/question_detail.html 파일을 수정해야 한다.
# D:\projects\mysite\templates\pybo\question_detail.html <h1>{{ question.subject }}</h1> <div> {{ question.content }} </div> <h5>{{ question.answer_set.count }} 개의 답변이 있습니다. </h5> <div> <ul> {% for answer in question.answer_set.all %} <li>{{ answer.content }}</li> {% endfor %} </ul> </div> <form action="{% url 'pybo:answer_create' question.id %}" method="post"> {% csrf_token %} <textarea name="content" id="content" rows="15"></textarea> <input type="submit" value="답변등록"> </form> |
question.answer_set.count는 답변 개수를 의미한다. 질문 내용과 답변 입력 창 사이에 답변 표시 영역을 추가했다. 질문 상세 페이지에 접속하면 아래와 같은 화면을 볼 수 있다. 파이보의 답변 저장, 답변 조회 기능을 완성하였다!
여기까지
'개발자모드 > 혼자공부하는파이썬' 카테고리의 다른 글
[파이썬/장고#11] 부트스트랩(Bootstrap) 다운로드 및 셋팅 / 부트스트랩 적용하여 쉽게 화면개발하기 (1) | 2022.08.30 |
---|---|
[파이썬/장고#10] 웹페이지에 스타일시트(CSS) 적용하기 (ft. 스태틱 디렉터리, style.css) (0) | 2022.08.29 |
[장고#08] URL 하드코딩 없애는 방법 (ft. URL별칭, 네임스페이스 사용) (1) | 2022.08.25 |
[장고#07] 질문 목록과 질문 상세 기능 구현 (ft. 템플릿등록, 화면추가, render 함수사용, URL매핑) (0) | 2022.08.23 |
[장고#06] 장고 Admin에서 모델 데이터 추가, 검색기능 추가 (0) | 2022.08.17 |
댓글