第 14 篇:交流的桥梁“评论功能”——HelloDjango 系列教程 (2)

django 的表单功能就是帮我们完成上述所说的表单处理逻辑,表单对 django 来说是一个内容丰富的话题,很难通过教程中的这么一个例子涵盖其全部用法。因此我们强烈建议你在完成本教程后接下来的学习中仔细阅读 django 官方文档关于 表单 的介绍,因为表单在 Web 开发中会经常遇到。

下面开始编写评论表单代码。在 comments 目录下(和 models.py 同级)新建一个 forms.py 文件,用来存放表单代码,我们的表单代码如下:

comments/forms.py from django import forms from .models import Comment class CommentForm(forms.ModelForm): class Meta: model = Comment fields = ['name', 'email', 'url', 'text']

要使用 django 的表单功能,我们首先导入 forms 模块。django 的表单类必须继承自 forms.Form 类或者 forms.ModelForm 类。如果表单对应有一个数据库模型(例如这里的评论表单对应着评论模型),那么使用 ModelForm 类会简单很多,这是 django 为我们提供的方便。之后我们在表单的内部类 Meta 里指定一些和表单相关的东西。model = Comment 表明这个表单对应的数据库模型是 Comment 类。fields = ['name', 'email', 'url', 'text'] 指定了表单需要显示的字段,这里我们指定了 name、email、url、text 需要显示。

关于表单进一步的解释

django 为什么要给我们提供一个表单类呢?为了便于理解,我们可以把表单和前面讲过的 django ORM 系统做类比。回想一下,我们使用数据库保存创建的博客文章,但是从头到尾没有写过任何和数据库有关的代码(要知道数据库自身也有一门数据库语言),这是因为 django 的 ORM 系统内部帮我们做了一些事情。我们遵循 django 的规范写的一些 Python 代码,例如创建 Post、Category 类,然后通过运行数据库迁移命令将这些代码反应到数据库。

django 的表单和这个思想类似,正常的前端表单代码应该是和本文开头所提及的那样的 HTML 代码,但是我们目前并没有写这些代码,而是写了一个 CommentForm 这个 Python 类。通过调用这个类的一些方法和属性,django 将自动为我们创建常规的表单代码,接下来的教程我们就会看到具体是怎么做的。

展示评论表单

表单类已经定义完毕,现在的任务是在文章的详情页下方将这个表单展现给用户,用户便可以通过这个表单填写评论数据,从而发表评论。

那么怎么展现一个表单呢?django 会根据表单类的定义自动生成表单的 HTML 代码,我们要做的就是实例化这个表单类,然后将表单的实例传给模板,让 django 的模板引擎来渲染这个表单。

那怎么将表单类的实例传给模板呢?因为表单出现在文章详情页,一种想法是修改文章详情页 detail 视图函数,在这个视图中实例化一个表单,然后传递给模板。然而这样做的一个缺点就是需要修改 detail 视图函数的代码,而且 detail 视图函数的作用主要就是处理文章详情,一个视图函数最好不要让它做太多杂七杂八的事情。另外一种想法是使用自定义的模板标签,我们在 页面侧边栏:使用自定义模板标签 中详细介绍过如何自定义模板标签来渲染一个局部的 HTML 页面,这里我们使用自定义模板标签的方法,来渲染表单页面。

和 blog 应用中定义模板标签的老套路一样,首先建立评论应用模板标签的文件结构,在 comments 文件夹下新建一个 templatetags 文件夹,然后创建 __init__.py 文件使其成为一个包,再创建一个 comments_extras.py 文件用于存放模板标签的代码,文件结构如下:

... blog\ comments\ templatetags\ __init__.py comments_extras.py ...

然后我们定义一个 inclusion_tag 类型的模板标签,用于渲染评论表单,关于如何定义模板标签,在 页面侧边栏:使用自定义模板标签 中已经有详细介绍,这里不再赘述。

from django import template from ..forms import CommentForm register = template.Library() @register.inclusion_tag('comments/inclusions/_form.html', takes_context=True) def show_comment_form(context, post, form=None): if form is None: form = CommentForm() return { 'form': form, 'post': post, }

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/zyypsp.html