본문 바로가기
개발자모드/혼자공부하는파이썬

[장고#09] 질문에 대한 답변 등록 기능 만들기 (답변저장, 답변조회)

by 요니L 2022. 8. 26.

 

 

앞에서 질문 등록, 조회 기능을 만들었다. 이번에는 답변 등록과 답변을 보여주는 기능을 만들어 보자.

 


답변 저장하고 표시하기

 

(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는 답변 개수를 의미한다. 질문 내용과 답변 입력 창 사이에 답변 표시 영역을 추가했다. 질문 상세 페이지에 접속하면 아래와 같은 화면을 볼 수 있다. 파이보의 답변 저장, 답변 조회 기능을 완성하였다!

 

 


 

여기까지

 

 

댓글