写一个简单的表单
为了在投票系统的详细页面中加入表单元素<form>,我们需要更新页面的模板。
polls/templates/polls/detail.html
<h1>{{ question.quesiton_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>
{% endfor %}
<input type="submit" value="vote"/>
</form>
一份简单的解释:
- 上面的模板包含了一个问题的单选表单。每个单选按钮的值是问题的选项id。每个单选按钮的名字都是"choice"。当有人选中了一个按钮并提交表单时,会发送POST数据choice=#(#表示选择的选项id)。
- 我们设置表单的action为{% url "polls:vote" question.id %},method="post"。使用method="post"很重要,因为提交表单的动作会改变服务端的数据。当你创建了一个会改变服务端数据的表单时,一定要使用method="post"。
- forloop.counter表示for标签已经循环的次数。
- 因为创建了一个POST表单,我们需要担心跨站请求伪造的攻击(简称为CSRF,全称Cross Site Request Forgeries)。Django使用{% csrf_token %}标签来保护服务器不受CSRF的攻击。很好用,不是吗?
现在,我们将创建一个Django视图函数来处理提交的数据,并使用这些数据完成一些功能。记的吗,在教程三里,我们为投票系统创建了一个URL清单?
polls/urls.py
url(r'^(?P<question_id>[0-9]+)/vote/$', views.vote, name='vote'),
在上个教程中我们创建了一个没有实现投票功能的vote()函数,但是下面将实现该功能:
polls/views.py
from django.shortcuts import render,
get_object_or_404
from django.http import HttpResponse, HttpResponseRedirect
from django.urls import reverse
from .models import Choice, Question
def vote(request, question_id):
question = Question.objects.get(pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
return render(request, 'polls:vote', {'question': question, 'error_message': 'oh, did not choose a radio.'})