1. 템플릿에 답변 등록 폼 추가
앞서 작성해두었던 question_detail.html을 다음과 같이 수정해서 답변의 내용을 입력할 수 있는 텍스트창, 저장할 수 있는 "답변등록" 버튼을 추가해준다. 답변을 저장하기 위한 URL은 form 태그의 action 속성에 {% url 'pybo:answer_create' question.id %}로 지정해주었다.
form 태그 바로 밑에 {% csrf_token %}은 보안에 관련된 항목으로 form으로 전송한 데이터가 실제 웹 페이지에서 작성한 데이터인지 판단해주는 가늠자 역할을 한다. 만약 해커가 엉뚱한 방법으로 데이터를 전송할 경우에는 서버에서 발행한 csrf_token 값과 해당 툴에서 보낸 csrf_token 값이 일치하지 않기 때문에 오류가 발생할 것이다.
따라서 form 태그 바로 밑에 {% csrf_token %} 태그를 항상 위치시키도록 해야 한다!!
<h1>{{ question.subject }}</h1>
<div>
{{ question.content }}
</div>
<form action="{% url 'notes:answer_create' question.id %}" method="post">
{% csrf_token %}
<textarea name="content" id="content" rows="15"></textarea>
<input type="submit" value="답변등록">
</form>
**csrf_token 사용을 위해서는 CsrfViewMiddleware 미들웨어가 필요한데 이 미들웨어는 settings.py의 MIDDLEWARE 항목에 디폴트로 추가되어 있으므로 별도의 설정은 필요 없다.
2. URL 매핑
위 템플릿에서 {% url 'pybo:answer_create' question.id %}라는 URL을 지정해주었으니, urls.py에서도 해당 URL 매핑을 등록해주어야한다. notes/urls.py를 다음과 같이 수정해서 URL 매핑을 등록한다.
from django.urls import path
from . import views
app_name = 'notes'
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'),
]
이제 http://localhost:8000/notes/answer/create/1/, http://localhost:8000/notes/answer/create/2/ 와 같은 페이지를 요청하면 views.answer_create 함수가 호출된다.
3. answer_create 뷰함수
위 url을 요청했을 경우 호출될 함수를 이제 작성해주어야한다.
/notes/views.py에 answer_create 함수를 추가하고 다음과 같이 작성하자.
from django.shortcuts import render, get_object_or_404, redirect
from django.utils import timezone
from .models import Question
###생략###
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('notes:detail', question_id=question.id)
question = get_object_or_404(Question, pk=question_id)은 이전 게시물에서도 설명했듯이, question_id 값을 통해 해당 데이터를 조회한다. 만약 해당 question_id가 존재하지 않으면 404 에러 페이지가 뜨도록 설정한다.
question.answer_set은 해당 질문에 대한 답변을 의미한다. Question과 Answer 모델은 외래키로 서로 연결되어있으므로 이와 같이 사용할 수 있다. question.answer_set.create은 해당 질문에 대한 답변을 생성한다.
request.POST.get('content')는 POST로 전송된 form 데이터 항목 중 content 값을 의미한다.
question.answer_set.create()가 어려우면 아래와 같이 작성해도 결과는 동일하다.
question.answer_set.create(content=request.POST.get('content'), create_date=timezone.now())
### == 동일 ###
answer = Answer(question=question, content=request.POST.get('content'), create_date=timezone.now())
answer.save()
마지막으로 답변을 생성한 후 다시 질문 상세 화면을 보여주기 위해 redirect 함수를 사용한다. redirect는 페이지 이동을 위한 함수이다. 그리고 detail 별칭은 question_id가 필요하므로 두번째 인수로 question.id를 전달한다.
4. 답변 저장
우선 답변을 입력해서 등록을 해보았다. 하지만 아직 답변을 등록한 내용을 볼 수 있는 코드를 작성하지 않았으므로 이 부분을 구현해야한다.
5. 답변 조회
작성한 답변을 질문 상세보기 화면에 표시하기 위해서 question_detail.html 템플릿을 아래와 같이 수정해준다. question.answer_set.count는 해당 질문에 대한 답변의 총 개수를 구해준다.
<h1>{{ question.subject }}</h1>
<div>
{{ question.content }}
</div>
<br>
<h5>{{ question.answer_set.count }}개의 답변이 있습니다.</h5>
<div>
<ul>
{% for answer in question.answer_set.all %}
<li>{{ answer.content }}</li>
{% endfor %}
</ul>
</div>
<br>
<form action="{% url 'notes:answer_create' question.id %}" method="post">
{% csrf_token %}
<textarea name="content" id="content" rows="15"></textarea>
<input type="submit" value="답변등록">
</form>
이제 이전에 등록한 답변들이 잘 출력되는 것을 볼 수 있다!
참고: https://wikidocs.net/73236
'Web > Django' 카테고리의 다른 글
장고(Django) GET과 POST를 활용하여 폼(Form) 작업하기 (0) | 2021.08.03 |
---|---|
Django(장고) static 디렉터리와 템플릿 상속 및 include 태그 사용 (0) | 2021.08.03 |
Django(장고) url 별칭과 네임스페이스 살펴보기 (0) | 2021.08.03 |
Django(장고) 템플릿과 데이터 조회 및 URL 매핑하기 (0) | 2021.08.02 |
Django(장고) 관리자 계정 생성 및 관리자 페이지 사용하기 (0) | 2021.08.02 |