Write a simple form
更新poll detail template(polls/detail.html).使得模版包含HTML<form>元素:
屏幕快照 2018-08-31 下午2.10.10.png
上面的模版为每一个问题选择显示一个单选按钮,每个单选按钮的值是相关问题选择的.每个单选按钮的名称是"choice".这意味着,当某人选择其中一个单选按钮并提交表单时,它将发送POST data choice= #.#是所选的ID,这是html表单的基本概念。
表单的动作设置为{% url 'polls:vote' question.id %},方法为post.使用post方法非常重要,因为提交表单的行为将改变数据服务器端。当要创建一个改变数据服务器端的表单时,使用post方法。
forloop计数器统计了for标记循环的次数。
因为我们创建了一个post表单,它可以修改数据。所以我们需要担心跨站点请求伪造。Django提供了一个非常容易使用的系统来防止这种情况的发生。简而言之,所有针对内部url的post表单都应使用{% csrf_token %}模版标记。
现在我们创建一个Django视图来处理提交的数据。我们为包含这一行的poll应用程序创建了一个URLconf。
屏幕快照 2018-08-31 下午2.51.20.png
我们还创建了vote()函数的虚拟实现。接下来创建一个真实的版本,将以下内容加到poll/view.py中。
屏幕快照 2018-08-31 下午2.53.55.png
request.POST是一个类似于字典的对象,可以通过键名访问提交的数据。在这种情况下,POST['choice']以字符串的形式返回所选选项的ID。
在增加选择数后,代码返回一个HttpResponseRedirect,而不是普通的HttpResponse.HttpResponseRedirect直接受一个参数:用户将被重定向到的URL。
在成功处理POST数据之后,应该总是返回一个HttpResponseRedirect.
在本例中,我们在HttpResponseRedirect构造函数中使用reverse()函数。此函数有助于在视图函数中硬编码URL。它给出了我们想要传递控件的视图的名称以及指向该视图的URL模式的可变部分。在本例中,使用教程3中设置的URLco f,这个reverse()调用将返回一个字符串。
屏幕快照 2018-08-31 下午3.26.25.png
3是question.id的值。重定向的URL将会调用results 视图来展示最后一页。
在某人对某个问题进行投票之后,vote()视图将重定向到该问题的结果页面。
屏幕快照 2018-08-31 下午3.32.11.png
这和课程3中detail()视图几乎是相同的。唯一不同的是模版名称。
现在创建polls/results.html模版:
屏幕快照 2018-08-31 下午3.35.33.png
现在在浏览器中访问/polls/1页面,对问题投票。可以看到每次投票后,results page都会更新。如果提交表单时没有选择,将会看到报错。
Use generic views: Less code is better
这些视图代表了web开发的一些常见情况。根据URL中传递的参数从数据库中获取数据,加载模版,并返回呈现的模版。因为这很常见,Django提供通用视图系统。
泛型视图抽象公告模式,以至于不需要编写python代码来编写应用程序。
让我们把poll应用程序转换为通用视图系统,这样我们就可以删除一些自己的代码。只需采取以下步骤转换:
1.URLconf转换
2.删除一些旧的,不需要的视图
3.基于Django通用视图引入新的视图。
Amend URLconf
首先,在polls/urls.py中修改URLconf如下:
屏幕快照 2018-08-31 下午5.27.44.png
注意:第二个和第三个模式路径字符串中匹配的模式名称已经从<question_id>更改为<pk>。
Amend views
屏幕快照 2018-08-31 下午5.46.58.png
我们用了两个通用视图:ListView 和Detail View.这两个视图分别抽象了“显示对象列表”和“显示特定类型对象的详细页面"的概念。
每个泛型视图都需要知道它将作用于哪个model.这是由model属性提供的
DetailView通用视图期望从URL中捕获的主键值叫pk,所以在通用视图中把question_id改为pk.
默认情况下,DetailView通用视图使用<app name>/<model name>_detail.html 模版。在本例中,使用的是“polls/question_detail.html".template_name的属性用来告诉Django 用了指定的模版名称而不是自动生成的默认模版名称。同时也给result 视图指定特定的模版。这用来保证result视图和detail视图被渲染为不同的外观。尽管它们都是Detail View渲染的不同场景。
同样的,ListView通用视图使用了默认的模版<app name>/<model name>_list.html.我们使用template_name 来告诉ListView 去使用已经存在的“polls/index.html”模版。
在之前的课程中,模版提供了包含question 和latest_question_list 上下文变量。DetailView的Question变量是自动提供的。由于我们使用了Django model(Question).Django可以为上下文变量提供确定适当的名称。然而,对ListView,自动生成的上下文变量是question_list.为了覆盖它,我们提供了context_object_name属性,指明我们想用latest_question_list替代。作为一种替代方法,你可以更改模版来匹配新的默认上下文变量。
网友评论