现在我们已经可以向数据表中添加数据,并且还可以将数据从数据表中检索并显示出来,但是我们添加数据时并不能真正的实现用户输入控制,这一节课我们将学会通过表单向数据表中添加数据
创建表单模版
创建调查问卷添加表单
在之前的add_question
视图函数中,我们每次刷新页面只能固定的提交相同的数据,通过添加表单我们可以向数据表中添加由用户填写的数据
创建polls/templates/polls/add_question.html模版
<form action="/polls/add/" method="post">
<table>
<tr>
<th>调查项目</th>
</tr>
<tr>
<td>
<textarea name="question_text" id="" cols="30" rows="10"></textarea>
</td>
</tr>
</table>
<table>
<tr>
<th>调查选项</th>
</tr>
<tr>
<td><input type="text" name="choice_1"></td>
<td><input type="text" name="choice_2"></td>
</tr>
</table>
<table>
<tr><td><input type="submit" value="添加"></td></tr>
</table>
</form>
- 在表单中将action指向add_question视图的url
- 表单的method设为post,表示数据通过post方式提交
- 目前我们的能力有限,只能固定的添加两个问题选项
修改ADD视图函数
相应的add_question视图函数也需要做一些相应的修改
修改add视图函数
def add_question(request):
if request.method == "POST":
pub_date = timezone.now()
question_text = request.POST['question_text']
q = Question(question_text=question_text, pub_date=pub_date)
try:
q.save()
except Exception as e:
return HttpResponse(e)
else:
for i in range(1, 3):
try:
choice_text = request.POST["choice_%s" % i]
q.choice_set.create(choice_text=choice_text)
except Exception as e:
return HttpResponse(e)
return render(request, "polls/add_question.html")
- 首先添加一条if语句,对
request.method
进行判断,当表单使用POST方法提交时,request.method
的值为“POST” - 如果数据是POST方式提交,那么可以通过
request.POST
对象提取表单数据,通过表单字段的name
值作为key
值
CSRF_TOKEN
此时访问/polls/add就可以出现提交表单,填写数据进行提交
但是会出现错误提示
Forbidden (403)
CSRF verification failed. Request aborted.
CSRF - Cross-site request forgery,即跨站攻击伪造,主要是保证表单数据只能由自己的站点提交,是一种用户识别方式
现在我们需要给表单添加上csrf_token
修改add_question模版
<form action="/polls/add/" method="post">
{% csrf_token %}
<table>
<tr>
<th>调查项目</th>
........
修改详情视图
现在可以添加一个调查问卷,然后在问卷详情页进行投票
修改详情页面模版
与添加问卷类似,我们需要给投票部分添加上一个表单,与一个提交按钮
<!-- 增加form -->
<form action="/polls/{{ question.id }}" method="post">
{% csrf_token %}
<table>
<tr>
<td>问卷选项</td><td></td>
</tr>
{% for choice in question.choice_set.all %}
<tr>
<td>{{ choice.choice_text }}</td>
<!-- 给复选框取名, 将value值设为id -->
<td><input type="radio" name="choice" value={{ choice.id }}/></td>
</tr>
{% endfor %}
<tr>
<!-- 增加按钮 -->
<td>
<input type="submit" value="投票">
</td>
</tr>
</table>
</form>
修改详情视图
.......
# 新增加部分
if request.method == "POST":
choice = question.choice_set.get(id=request.POST['choice'])
choice.votes += 1
choice.save()
return render(request, 'polls/detail.html', {'question': question})
添加结果显示
在之前的模版中并没有显示投票结果,现在添加结果页面,将投票结果显示出来
添加polls/result.html
<table>
{% for choice in question.choice_set.all %}
<tr>
<td>{{ choice.choice_text }}</td> <td>{{ choice.votes }}</td>
</tr>
{% endfor %}
</table>
添加views.result视图函数
在这里,我们可以直接使用get_object_or_404
便捷函数来读取数据,省去异常处理
def result(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/result.html', {'question': question})
添加url规则
我们希望用户通过/polls/result/question_id方式访问结果
修改urls,添加一条规则
urlpatterns = [
path("", views.index, name="index"),
path("add", views.add_question, name="add"),
path('<int:question_id>/', views.detail, name='detail'),
path('result/<int:question_id>', views.result)
]
修改列表页面
现在还需要为结果页提供一个入口,也就是用户可以通过链接点击查看的地方,我们把这个链接放在列表页面,当用户进入列表页面,点击查看“投票结果”,即可查看对应调查问题的投票结果
{% for question in question_list %}
<li>
<a href="/polls/{{ question.id }}/">{{ question.question_text }}</a>
<br>
<a href="/polls/result/{{ question.id }}">查看结果</a>
</li>
{% endfor %}
现在访问一下你的页面,可以查看结果了没
讨论区