上善若水。水善利万物而不争
——老子《道德经》
本节内容
- 网页中的表单定义
- 表单提交数据的处理
1. 网页中的表单定义
网页中的表单是前端页面中非常重要的一部分,我们结合官方文档进行讲解
首先改造我们的问题详细信息页面details.html
,用于展示问题的同时,展示对应的解决方案;对于解决方案可以进行投票
1.1 改造mysite/polls/templates/details.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<title>详细问题展示</title>
<link rel="stylesheet" href="">
</head>
<body>
<!-- 展示问题描述信息 -->
<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>
{% endfor %}
<input type="submit" value="Vote投票">
</form>
</body>
</html>
在上述代码中,出现了大量的之前的章节中没有介绍的内容,我们一一说明一下。
-
action="{% url 'polls:vote' question.id %}"
:表单中的action是要提交的地址,我们通过配置化的URL路由进行处理 -
forloop.counter
:表示循环当前正在进行的次数,第一次循环(1),第二次循环(2)以此类推
*question.choice_set.all
:通过question
对象,关联查询对应的所有的Choice
对象(对应的查询过程,Django在底层已经帮我们自动处理了,类似select * from choice where question_id = #{id}
) -
error_message
:这个是我们后面再改造detail视图处理函数时,要添加的一个保存错误信息的变量,这里主要用于展示错误信息
*{%csrf_token%}
:这是一个Django内置的指令,主要用于预防跨域请求伪造攻击的(在其他的网页应用中,伪造的跨域请求攻击是一件让人头疼的事情,Django这点做的非常棒呢!)
注意:关于模板视图和模型对象中用到的大部分的API,后续的章节中会有介绍的哦,支持一下我们吧
1.2 改造视图处理函数views.vote
接下来,对于表单提交的数据,我们需要在视图处理函数中接收到并且进行后续的处理
# 定义投票结果
def vote(request, question_id):
# 获取查询的问题对象
question = get_object_or_404(Question, pk=question_id)
print(request.POST)
try:
select_choice = question.choice_set.get(pk=request.POST['choice'])
except Exception as e:
print(e)
return render(request, "details.html",
{
"question": question,
"error_message": "你的问题还没有发布解决方案"
})
else:
# 投票数量增加1
select_choice.votes += 1
# 保存到数据库
select_choice.save()
# 代码中使用配置的方式跳转到指定的路由
return HttpResponseRedirect(reverse("polls:results", args=(question.id,)))
对于上述代码,我们做一个简单的介绍,相信大家也就能看得明白了
-
request.POST
:是一个用于接收表单通过POST提交的数据的方式 -
request.POST["choice"]
:就是接收用户通过POST方式提交的表单中属性为choice
的数据的,类似的还有request.GET['attr']
;通过这样的方式获取数据,有可能会出现异常(当属性在表单中不存在时出现KeyError
异常) -
HttpResponseRedirect
:这是类似前面我们学过的HttpResponse处理类,主要是用于响应用户的请求处理的,它比HttpResponse
更加好用的是可以附带独立的参数列表;最后响应的是用户的请求会被重定向而不是转发。 -
reverse()
:这个函数主要是将之前我们处理的过程中操作的硬编码格式,转换成路由配置的格式,方便统一维护的操作。
1.3 改造results
视图函数和mysite/polls/templates/results.html
界面
views.results
视图处理函数主要是用于进行问题数据查询并跳转到视图界面的,如下:
def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, "results.html", {"question":question})
results.html网页主要是用于进行问题和对应解决方案的展示使用的,和details.html界面大同小异
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<!-- 展示问题信息 -->
<h2>{{question.question_text}}</h2>
<!-- 循环遍历所有的解决方案 -->
<ul>
{% for c in question.choice_set.all %}
<li>方案:{{c.choice_text}}----[投票结果{{c.votes}}]vote{{ c.votes|pluralize }}</li>
{% endfor %}
</ul>
<a href="{% url 'polls:detail' question.id%}">继续投票?</a>
</body>
</html>
1.4, 功能测试
接下来,我们重启项目,开始投票功能的测试
打开首页
查看问题信息
投票处理
这节关于表单的处理就先介绍到这里,对于大家常规的项目使用已经可以完全满足了。下一节内容将对我们页面中的样式进行处理,让页面看着更加的优美