概述
在HTML页面中,form表单是通过<form></form>
标签来定义的,可以将数据提交给服务器,如:
<form action="demo/hello" method="get">
First name: <input type="text" name="fname"><br>
Last name: <input type="text" name="lname"><br>
<input type="submit" value="提交">
</form>
<form>
标签中可以包含许多的表单元素,<input>
元素是form表单中最重要的元素,该元素有很多形态,可以根据type指定:
<input type="text" name="name" value="zhangsan"></input>
<input type="radio" name="sex" value="male"></input>
<input type="password" name="password"></input>
<input type="submit" value="Submit">
<form>
标签的action
属性定义了在提交表单时执行的动作,如果不指定默认当前页面;
<form>
标签的method
属性定义在提交表单时使用的HTTP请求方法,如果不指定默认GET方法。
Django中的表单处理
处理表单数据是一个复杂的过程,要对数据进行校验、显示等等,因此Django中提供了Form
类来描述一个form表单并决定如何工作和显示,大大简化了这些操作。
Form和<form>
的关系跟Model和数据库的关系类似。Model会将定义的字段映射到数据库中,而Form则会将定义的字段映射到<input>
表单元素中。此外还提供了ModelForm类用于将Model中的字段通过Form映射到<input>
元素中。
在向view中渲染一个Model时,流程一般为:
- 1.在视图中从数据库获取要显示的数据
- 2.将它传递给模板上下文
- 3.使用模板变量将其扩展为HTML标记
渲染Form也类似,不过区别在于,如果一个Model中没有包含数据时,在渲染时模板中为空即可,但是如果一个form表单中数据为空时,也对其进行渲染,以提示用户,这是更加友好的一种方式。
在处理Model实例时,会从View中获取它,当处理form时,会在View中实例化它。
下面是Django中操作表单的最基本使用示例:
- step1.首先定义一个Form类,并定义Form类字段,以创建对应表单中的表单元素:
# forms.py
from django import forms
class NameForm(forms.Form):
# 相当于<input type="text">
name = forms.CharField(label="your name", max_length=40)
- step2.定义一个View,在View中获取Form实例,并传给模板文件:
from django.shortcuts import render
from .forms import NameForm
from django.http import HttpResponse
def get_name(request):
if request.method == 'POST':
form = NameForm()
if form.is_valid():
return HttpResponse('/thanks/')
else:
form = NameForm()
return render(request, 'formdemo/name.html', {'form': form})
- step3.定义模板,用来显示View中要进行渲染的Form:
<form action="/your-name/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>
完成以上三步后,在浏览器中访问get_name视图的url,一个form表单则会显示出来。
在获取Form实例时,如果是GET
请求,则会创建一个空的Form实例,传递给模板上下文;如果是POST
请求,则会创建一个Form实例,并且将request中的数据填充给它,这个过程称为“绑定表单”。
Form中提供了is_valid()
方法,用于判断提交给Form实例的数据是否有效。如果该方法返回值为Flase,则会将Form中的数据重新带回到模板文件中,填充给HTML中的form表单,并根据需要进行编辑和改正。如果返回True,则form中所有验证的数据都会包含在cleaned_data
属性中,在重定向之前,可以利用该属性将数据保存到数据库或者做其他处理。
Form对应的模板
如上例所实现一样,在模板文件中,不需要太多的工作,所有form中的数据和属性都会从DTL的{{ form }}
中解析为HTML形式的<form>
中。
{% csrf_token %}
是CSRF标记,Cross Site Request Forgeries. 使用该标记可以防止CRSF。
结合以上总结,要使用一个表单,应该由Django的Form
类进行描述定义,由View
生成该Form实例进行处理,并呈现为HTML的<form>
。
Form常用属性和方法
cleaned_data
:包含所有提交到form的有效数据的字典。
is_valid()
:判断提交到Form中的数据是否有效;
is_bound()
:判断Form是否进行了绑定;
ModelForm
如果通过表单来对Django的Model直接进行处理,比如将提交的数据实例化为一个Model实例并添加、编辑等,可以使用ModelForm
。
绑定表单和非绑定表单
- 非绑定表单:没有数据关联,呈现给用户的将是空的或是默认值;
- 绑定表单中包含提交的数据,因此可以用来校验数据,如果绑定了无效的数据,则会包含一些内联错误告诉用户要更正哪些数据。
is_bound
属性可以判断Form是否绑定。
Field类
在定义Form时,必须定义表单的字段——FormField,来指定要提交的数据类型,每个表单字段都有一个相应的Widget
类,它又对应于一个HTML表单控件。可以在定义字段时使用widget=
来指定Widget。常用的FormField及其对应的Widget和HTML如下表所示:
Field | 对应Widget | 对应HTML元素 |
---|---|---|
CharField |
TextInput | <input text="text"> |
DateTimeField |
TextInput | <input type="text"> |
ChoiceField |
Select | <select><option ...>...</select> |
FileField |
ClearableFileInput | <input type="file" ...> |
DateField |
DateInput | <input type="file" ...> |
Field常用属性
required
:默认情况下,每个字段的值都是必须的,因此当传入空值,如None或者''
时,clean()
方法会引发一个ValidationError
异常,因此如果在定义字段时指定required=False
,则可以允许为空,如:
name = forms.CharField(required=False)
label
:指定该字段对用户来说更加友好;
Widget类
Widget是Django中对HTML<input>
元素的表示方式,每个Field字段都有一个Widget相对应,负责处理HTML的渲染以及从与该Widget对应的GET / POST字典中提取数据。
指定一个Widget
为一个Field指定一个Widget,可以通过widget
属性进行:
description = forms.CharField(widget="textarea")