[Django] 기본 구조 - 데이터 저장

haejun-kim·2020년 7월 6일
1

[Django]

목록 보기
7/20
post-thumbnail

답변 등록 버튼

/question_detail.html

<form action="{% url 'review:answer_create' question.id %}" method="POST">
{% csrf_token %}
<textarea name="content" id="content" rows="15"></textarea>
<input type="submit" value="답변등록">
</form>

textarea, button

답변 내용을 적을 수 있는 textarea와 답변을 등록하는 답변버튼을 만들었다.

답변 저장 URL

{% url 'review:answer_create' question.id %} 은 답변을 저장하는 URL이며 데이터를 보내는 방식은 POST로 작성했다.

csrf_token

form태그 바로 밑에 보이는 {% csrf_token %}은 보안에 관련된 항목으로 form으로 전송된 데이터가 실제 웹페이지에서 작성된 데이터인지를 판단해 주는 가늠자 역할을 한다. 기타 다른 해킹 툴등에 의해서 데이터가 전송될 경우에는 서버에서 발행한 csrf_token값과 해당 툴에서 보낸 csrf_token 값이 일치하지 않기때문에 오류가 발생한다.
따라서 form태그 바로 밑에 {% csrf_token %} 을 항상 위치시키도록 해야 한다.


URL추가

위와 같은 상태로 로컬 서버를 구동하고 상세페이지를 들어가보면 다음과 같은 에러가 발생한다.

answer_create 를 아직 만들어주지 않았기 때문에 발생하는 에러이기 때문에, 이부분을 추가해줘야한다.
/review/urls.py

path("answer/create/<int:question_id>/", views.answer_create, name="answer_create"

뷰 함수 추가

이제 views.py에서 answer_create함수를 작성해주면 URL매핑이 끝난다.

from django.shortcuts import redirect
from django.utils import timezone

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("review:detail", question_id=question.id)

redirect

답변을 생성한 후 상세조회 화면을 호출하기 위해 redirect함수를 사용했다. redirect함수는 페이지 이동을 위해 장고가 제공하는 함수이다. 여기서는 답변 저장 후 pybo:detail 페이지로 이동하기 위해 사용되었다.

request.POST.get("content")

첫번째 매개변수 request 객체를 통해 폼에서 입력한 답변 데이터를 읽을 수 있다. request.POST.get('content')는 POST로 전송된 폼(form) 데이터 항목 중 content의 값을 의미한다.

그리고 답변을 생성하기 위해 question.asnswer_set.create 를 사용하였다. question.answer_set은 질문의 답변을 의미한다. QuestionAnswer 모델은 서로 ForeignKey 로 연결되어 있기때문에 이처럼 사용할 수 있다.


❗️답변을 저장하는 또 다른 방법은 다음처럼 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()

question_id

redirect('pybo:detail', question_id=question.id)

에서 사용된 question_id는 다음과 같이 정의된 URL매핑에 question_id 를 전달하기 위해 필요하다.

path('<int:question_id>/', views.detail, name='detail'),

답변 저장

메인화면에서 상세화면을 누르면 이런 화면이 이제 나타난다.

답변을 등록할 수 있는 구역에 글을 작성하고 답변을 등록해보아도 아직 보여줄 템플릿을 수정하지 않았기 때문에 에러가 발생한다.😂 템플릿을 마저 수정해주자..

답변 조회

/templates/review/question_detail.html

<h5>{{ question.answer_set.count }}개의 답변이 있습니다.</h5>
<div>
    <ul>
        {% for answer in question.answer_set.all %}
            <li>
                {{ answer.content }}
            </li>
        {% endfor %}
    </ul>
</div>

question.answer_set.count를 통해 질문에 달린 답변의 갯수를 카운트해서 표시해주었다. qeustion.answer_set.all는 질문에 달린 답변의 전체인데 이 전체를 반복문을 통해 answer에 순차적으로 넣어주었고, <li> 태그를 사용해 이 순차적으로 넣은 answercontent 를 표시해주었다.
이제 다시 답변을 등록해보자.

이런식으로 답변이 제대로 달리며, 답변을 추가할때마다 답변의 갯수도 함께 증가하는것을 확인할 수 있다.

0개의 댓글