Django编写您的第一个Django应用 四
Write a minimal form
更新民意调查详细信息模板(“ polls / detail.html”),以便该模板包含一个HTML <form>元素:

效果:

快速总结:
- 上面的模板为每个问题选择显示一个单选按钮。
value每个单选按钮的是相关联的问题的选择的ID。name每个单选按钮的是"choice"。这意味着,当某人选择一个单选按钮并提交表单时,它将发送POST数据choice=#,其中#是所选选项的ID。这是HTML表单的基本概念。 - 我们将表单设置
action。非常重要,因为提交此表单的行为将改变服务器端的数据。每当您创建更改数据服务器端的表单时,请使用。本技巧不是特定于Django的。一般来说,这是良好的Web开发实践。{% url 'polls:vote' question.id %}method="post" forloop.counter指示for标签经过其循环的次数- 由于我们正在创建POST表单(可能具有修改数据的效果),因此我们需要担心跨站点请求伪造。值得庆幸的是,您不必太担心,因为Django随附了一个有用的系统来防御它。简而言之,所有针对内部URL的POST表单都应使用 模板标记。
{% csrf_token %}
现在,让我们创建一个Django视图,该视图可处理提交的数据并对其进行处理。记住,在教程3中,我们为民意调查应用程序创建了一个URLconf,其中包括以下行:
path('<int:question_id>/vote/', views.vote, name='vote'),
我们还创建了该vote()函数的虚拟实现。让我们创建一个真实的版本。将以下内容添加到polls/views.py:

效果:



该代码包含了我们在本教程中尚未涉及的一些内容:
-
request.POST是类似于字典的对象,可让您通过键名访问提交的数据。在这种情况下request.POST['choice']以字符串形式返回所选选项的ID。request.POST值始终是字符串。 -
请注意,Django还提供
request.GET了以相同方式访问GET数据的方法-但我们request.POST在代码中明确使用,以确保仅通过POST调用更改数据。 -
request.POST['choice']KeyError如果choice未在POST数据中提供。上面的代码检查KeyError并重新显示带有错误消息的问题表单(如果choice未给出)。 -
在增加选择计数后,代码将返回
HttpResponseRedirect而不是normalHttpResponse。HttpResponseRedirect接受一个参数:将用户重定向到的URL正如上面的Python注释所指出的,
HttpResponseRedirect在成功处理POST数据后,您应该始终返回a 。本技巧不是特定于Django的。一般来说,这是良好的Web开发实践。 -
在此示例
reverse()中,我们在HttpResponseRedirect构造函数中使用该函数 。此功能有助于避免在视图功能中对URL进行硬编码。它提供了我们想要将控制权传递给的视图的名称以及指向该视图的URL模式的可变部分。在这种情况下,使用我们在教程3中设置的URLconf ,此reverse()调用将返回一个字符串,例如'/polls/3/results/'其中3是的值question.id。然后,此重定向的URL将调用'results'视图以显示最后一页。
有人对问题进行投票后,vote()视图将重定向到该问题的结果页面。让我们写一个视图:

现在,创建一个polls/results.html模板:

效果:

点击 Vote again?时,返回投票界面

使用通用视图:代码越少越好
在detail()(从教程3)和results() 意见是非常短-和,以上,多余的,因为提到的。index() 显示民意测验列表的视图是相似的。
这些视图代表了基本Web开发的一种常见情况:根据URL中传递的参数从数据库获取数据,加载模板并返回渲染的模板。
因为这很常见,所以Django提供了一个捷径,称为“通用视图”系统。
让我们将民意调查应用程序转换为使用通用视图系统,以便我们删除一堆自己的代码。我们必须采取一些步骤进行转换。我们会:
- 转换URLconf。
- 删除一些旧的不需要的视图。
- 根据Django的通用视图介绍新视图。
修改URL配置
首先,打开polls/urls.pyURLconf并按如下所示进行更改:

修改views
接下来,我们将删除我们的老index,detail和results 视图,并使用Django的通用视图代替。为此,请打开 polls/views.py文件并按如下所示进行更改:

我们在这里使用两个通用视图: ListView和 DetailView。这两个视图分别抽象了“显示对象列表”和“显示特定类型的对象的详细信息页面”的概念。
- 每个通用视图都需要知道它将作用于什么模型。这是使用
model属性提供的。 - 该
DetailView通用视图预计从URL中捕获的主键值被调用"pk",所以我们已经改变question_id,以pk用于通用视图。

浙公网安备 33010602011771号