笔记主要基于官方文档,从中提取要点和记录笔记,关键处包含了官方文档链接。详见官方文档。
官方文档:Django documentation
博客推荐:Django2.2教程
目录
Django 提供了一个丰富的框架来帮助创建表单和处理表单数据。
表单官方文档:表单;基础部分文档: 概览 | 表单 API | 内建字段 | 内建 widgets;
1.HTML表单
在HTML中,表单 <form>...</form>
可以收集其内部标签中的用户输入,然后将数据发送到服务端。
一个HTML表单必须指定两样东西:
- 目的地:用户数据发送的目的URL
- 方式:发送数据所使用的HTTP方法
以Django Admin站点登录表单的HTML为例:
<form action="/admin/login/?next=/admin/" method="post" id="login-form">
<input type='hidden' name='csrfmiddlewaretoken'
value='NNHZaDVJGduajNMECXygKZkAt8vyEcw9HS2qm2Vdf7brDZrA0qK1R0I7M2p3TKcs' />
<div class="form-row">
<label class="required" for="id_username">用户名:</label>
<input type="text" name="username" autofocus maxlength="254" required id="id_username" />
</div>
<div class="form-row">
<label class="required" for="id_password">密码:</label>
<input type="password" name="password" required id="id_password" />
<input type="hidden" name="next" value="/admin/" />
</div>
<div class="submit-row">
<label> </label> <input type="submit" value="Log in" />
</div>
</form>
- 表单数据
<form>
的action
属性指定URL,告诉浏览器表单应该发往哪里; method
属性指定HTTP方法——如post
;(GET 和 POST)- 表单包含了一些
<input>
元素:type="text"
用于用户名,type="password"
用于密码,type="submit"
用于“登录"按钮。 - 当点击
<input type="submit" value="Log in">
元素时,数据将发送给指定URL。
通常情况下,我们需要自己手动在HTML页面中,编写form标签和其内的其它元素。但这比较麻烦,Django的表单功能可以简化和自动化上述工作的大部分内容。
2.Django 中的表单
Django表单会处理涉及的三个不同部分:
- 准备并重组数据,以便下一步的渲染
- 为数据创建HTML 表单
- 接收并处理客户端提交的表单及数据
您 可以 手动编写代码来实现,但Django 可以帮你完成所有这些工作。
编写Django的form表单,非常类似我们在模型系统里编写一个模型。在模型中,一个字段代表数据表的一列,而form表单中的一个字段代表
<form>
中的一个<input>
元素。Django表单系统的核心组件是Form
类。
实例化、处理和渲染表单
在Django中渲染一个对象的时候,我们通常:
- 在视图中获取它(例如从数据库中取出)
- 将它传递给模板上下文
- 使用模板变量将它扩展为HTML标记
在模板中渲染表单几乎与渲染任何其他类型的对象的一样,但是也存在一些关键性的差异。
3.使用Django的表单
通常三个步骤:
- 编写表单类
- 视图处理
- 模板处理
假设希望在网站上创建一张简易的表单,用来获取用户的名字。需要在模板中使用类似代码:
<form action="/your-name/" method="post">
<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" value="{{ current_name }}">
<input type="submit" value="OK">
</form>
与之相关的需要相关的表单,在表单中做相关处理,做验证等等。使用Django表单可完成以上大部分工作。
3.1.编写Form
类
通过Django提供的Form类可以自动生成上面的表单,不再需要手动在HTML中编写。
在当前app内新建一个forms.py
文件(就像views.py
,models.py
等):
# forms.py
from django import forms
class NameForm(forms.Form):
your_name = forms.CharField(label='Your name', max_length=100)
首先它在HTML的 <input>
上增加了 maxlength="100"
(这样浏览器会在第一时间阻止用户输入超过这个数量的字符串)。其次它还会在Django收到浏览器传过来的表单时,对数据长度进行验证(也就是服务器端验证)。
注意:
- 提前导入forms模块
- 所有的表单类都要继承forms.Form类
- 每个表单字段都有自己的字段类型比如CharField,它们分别对应一种HTML语言中的
<form>
元素中的表单元素。这一点和Django模型系统的设计非常相似。- 例子中的label用于设置说明标签
max_length
限制最大长度为100。它同时起到两个作用,一是在浏览器页面限制用户输入不可超过100个字符,二是在后端服务器验证用户输入的长度不可超过100。- 每个Django表单的实例都有一个内置的
is_valid()
方法,用来验证接收的数据是否合法。如果所有数据都合法,那么该方法将返回True,并将所有的表单数据转存到它的一个叫做cleaned_data
的属性中,该属性是以个字典类型数据。
将上面的表单渲染成真正的HTML元素,其内容如下:
<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" maxlength="100" required />
注意,它不包含<form>
标签本身以及提交按钮!为什么要这样?方便你自己控制表单动作和CSS,JS以及其它类似bootstrap框架的嵌入!
3.2.视图处理
表单数据由视图来处理,一般和发布这个表单用的是同一个视图,以重用一些相同的逻辑。
为了处理表单,需要将它实例化到我们希望发布的URL的对应的视图中:
# views.py
from django.shortcuts import render
from django.http import HttpResponseRedirect
from .forms import NameForm
def get_name(request):
# 如果form通过POST方法发送数据
if request.method == 'POST':
# 接受request.POST参数构造form类的实例
form = NameForm(request.POST)
# 验证数据是否合法
if form.is_valid():
# 处理form.cleaned_data中的数据
# ...
# 重定向到一个新的URL
return HttpResponseRedirect('/thanks/')
# 如果是通过GET方法请求数据,返回一个空的表单
else:
form = NameForm()
return render(request, 'name.html', {'form': form})
- 对于GET方法请求页面时,创建一个空的表单实例并将其放置在模板上下文中进行渲染,返回空的表单,让用户可以填入数据;
- 对于POST方法,接收表单数据,并验证;
- 如果数据合法,按照正常业务逻辑继续执行下去;
- 如果不合法,返回一个包含先前数据的表单给前端页面,方便用户修改
详见官方文档。
3.3.模板处理
Django的模板中,我们只需要按下面处理,就可以得到完整的HTML页面:
<form action="/your-name/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
所有的表单字段及其属性都将通过Django模板语言从 {{ form }}
中被解包成HTML标记。
注意:
<form>...</form>
标签要自己写;- 使用POST的方法时,必须添加
{% csrf_token %}
标签,用于处理csrf安全机制;{{ form }}
代表Django为你生成其它所有的form标签元素,也就是我们上面做的事情;- 提交按钮需要手动添加!
以上是入门需要了解的内容。
4.详解 Form 类
模型和表单
实际上,如果您的表单是要直接用来添加或编辑Django模型,用 ModelForm ,可以省时、省力、省代码,因为它会根据
Model
类构建一张对应字段及其属性的表单。参考:从模型创建表单
了解:绑定的和未绑定的表单实例
4.1.字段详解
实际上,Django的表单模块为我们内置了许多表单字段。
见下面表单:
from django import forms
class ContactForm(forms.Form):
subject = forms.CharField(max_length=100)
message = forms.CharField(widget=forms.Textarea)
sender = forms.EmailField()
cc_myself = forms.BooleanField(required=False)
这个例子中,我们的表单有四个字段: subject
、 message
、 sender
和 cc_myself
。用到三种可用的字段类型: CharField
、 EmailField
和 BooleanField
;
完整的字段类型清单请参看 Form fields 。
4.2.Widget控件
每个表单字段都有一个相对应的 控件类 ,这个控件类又有对应的HTML表单的一种input元素类型,比如 <input type="text">
。需要在HTML中实际使用什么类型的input,就需要在Django的表单字段中选择相应的field。比如要一个<input type="text">
,可以选择一个CharField
。
4.3.字段数据
无论用表单提交了什么数据,一旦通过调用 is_valid()
验证成功( is_valid()
返回 True
),已验证的表单数据将被放到 form.cleaned_data
字典中。就可以从form.cleaned_data
字典中读取所有的表单数据。
在视图中处理表单数据的例子:
# views.py
from django.core.mail import send_mail
if form.is_valid():
subject = form.cleaned_data['subject']
message = form.cleaned_data['message']
sender = form.cleaned_data['sender']
cc_myself = form.cleaned_data['cc_myself']
recipients = ['[email protected]']
if cc_myself:
recipients.append(sender)
send_mail(subject, message, sender, recipients)
return HttpResponseRedirect('/thanks/')
5.使用表单模板
只需将表单实例放到模板的上下文中即可。因此,如果表单在上下文中叫 form
,那么 {{ form }}
将渲染它相应的 <label>
和 <input>
元素。
表单渲染格式
{{ form }}
模板语言,能简单地将表单渲染到HTML页面中。对于 <label>
/ <input>
对,还有其他输出选项:
{{ form.as_table }}
将表单渲染成一个表格元素,每个输入框作为一个<tr>
标签{{ form.as_p }}
将表单的每个输入框包裹在一个<p>
标签内{{ form.as_ul }}
将表单渲染成一个列表元素,每个输入框作为一个<li>
标签
注意:
- 必须自己提供外层的
<table>
或<ul>
元素。- 一张表单的输出 不 包含外层
<form>
标签以及submit
控件。这些必须由你自己提供。
实例和更多信息见官方文档:表单渲染格式。
手动渲染字段
直接{{ form }}
虽然好,但是往往还达不到要求,比如要使用CSS和JS,要引入Bootstarps框架,这都需要对表单内的input元素进行额外控制。
可以通过{{ form.name_of_field }}
获取每一个字段,然后分别渲染;
label标签甚至可以用label_tag()
方法来生成;
详见官方文档。
以上仅为基础内容,更多详见官方文档。表单官方文档:表单: 概览 | 表单 API | 内建字段 | 内建 widgets;
-----end-----