오늘은 투표기능이 동작하도록 간단한 폼을 만들어보겠다.
detail.html을 수정하고 vote 뷰에도 기능을 추가하자.
간단한 폼 만들기
polls/templates/polls/detail.html을 다음과 같이 수정하자.
<h1>{{ question.question_text }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{% endif %}
<form action="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{forloop.counter}}" value="{{choice.id}}">
<label for="choice{{forloop.counter}}">{{choice.choice_text}}</label><br>
{% endfor %}
<input type="submit" value="Vote">
</form>
각 기능에 대해 알아보자.
- form 태그는 사용자가 답변 항목을 선택하고 전달할 수 있도록 만든다. 사용자가 선택한 항목의 번호를 vote 뷰를 전달하도록 action 속성에 vote URL이 출력되게 url 템플릿 태그를 사용한다.
- 위의 form 템플릿은 각 질문 선택 항목에 대한 라디오 버튼을 표시한다. 각 라디오 버튼의 value는 연관된 질문 선택 항목의 ID 이다. input type이 radio로 설정되어 있는 것을 확인할 수 있을 것이다.
- method 속성에 써있는 post는 HTTP 메서드 중 하나이며 서버로 정보를 전달할 때 사용하는 일반적인 방법이다.
- forloop.counter는 템플릿 문법에서 제공하는 기능 중 하나로 반복문의 반복 횟수를 출력해주는 기능을 한다.
- csrf_token은 CSRF(Cross Site Request Forgeries) 공격을 막기 위한 수단 중 하나이다. 즉, 방금 서버로 들어온 요청이 사이트 내부에서 온 것이 맞는지 확인하는 용도로 csrf_token의 값을 사용한다. (POST form을 생성 시, csrf를 염두에 두었어야했다. 하지만, django에선 모든 post form은 {% csrf_token %}이라는 템플릿 태그를 사용하여 csrf로부터 보호해준다.)
이제, detail.html에서 만들어진 정보를 받을 수 있게 vote 뷰를 수정해보자. polls/views.py를 다음과 같이 수정하자.
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
# Redisplay th question voting form
return render(request, 'polls/detail.html', {'question': question,
'error_message': "You didn't select a choice,"})
else:
selected_choice.votes += 1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:results', args=(question.id, )))
일단, request.POST[변수이름]을 통해 전달받은 변수의 값들을 확인할 수 있다. 즉, 전송된 자료에 접근할 수 있도록 해주는 사전과 같은 객체이다. 이 때 전달되는 값(request.POST)은 항상 문자열이기 때문에 문자열이라는 사실을 기억하자.
만약, 전달받은 답변이 해당 투표 항목에 없다면 다시 상세 페이지로 이동한다. 이 때 답변을 선택하지 않았다는 error message도 같이 전달한다.
반대로, 제대로된 답변을 선택한 것이라면 해당 답변의 답변 수를 1 증가 시키고 결과 화면으로 이동한다.
이제, 결과를 출력하는 result 뷰도 변경하자. polls/views.py를 다음과 같이 변경한다.
def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question': question})
polls/templates/polls/results.html도 만들어 준다. results.html 내의 코드는 다음과 같이 작성한다.
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>
<a href="{% url 'polls:detail' question.id %}">Vote again?</a>
results.html은 각 답변 항목과 투표 수를 한꺼번에 보여준다.
다음 글에서는 제너릭 뷰를 사용해 보겠다.
'프로젝트 > 파이썬 장고를 이용한 웹페이지 만들기' 카테고리의 다른 글
[+] django project에 템플릿 확장하기 (0) | 2020.04.18 |
---|---|
9. 튜토리얼 따라하기 - 설문조사(4) (0) | 2020.02.14 |
7. 튜토리얼 따라하기 - 설문조사(2) (0) | 2020.02.06 |
6. 튜토리얼 따라하기 - 설문조사(1) (0) | 2020.02.02 |
5. 관리자 계정 생성하기 (0) | 2020.01.30 |