Django 中的表单
表单,在前端页面中属于最常见的一个东西了。基本上网站信息的提交都用到了表单,记得刚学习前端页面时就照着网上的例子敲了一个登录的表单。话不多说,来看一看Django中优雅的表单系统:Form
Form 表单的功能
- 自动生成HTML表单元素
- 检查表单数据的合法性
- 回显功能(验证错误,输入数据不会被清空)
- 数据类型转换(转换成相应的pyhon类型)
表单小试
通常提交数据就是由HTML表单向后台传递信息,后台通过request.GET[] 或request.POST[]获取。
而使用Django表单则是这样的:
首先在APP模块中建立一个 forms.py 文件
#forms.py
from django import forms
class LoginForm(forms.Form):
account = forms.CharField()
password = forms.CharField()
email = forms.EmailField()
创建对应的视图函数
#views.py
from django.shortcuts import render
from django.http import HttpResponse
from .forms import LoginForm
def login(request):
if request.method == 'POST':
form = LoginForm(request.POST)
if form.is_valid():
return HttpResponse("登录成功!")
else:
form = LoginForm()
return render(request,'login.html',{'form':form})
建立对应的模板 login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>form demo</title>
</head>
<body>
<div align="center" style="height: 400px;width: 100px">
<form action="#" method="post">
{% csrf_token %}
{{ form }}
<button type="submit" id='sum'>提交</button>
</form>
</div>
</body>
</html>
配置 urls 一些基本的配置(比如模板,路由)就直接跳过了。
直接访问地址就显示出这样一个简单的界面,由html文件可以看到并没有js代码对数据有效性进行验证,但此时如果不输入内容或输入错误格式提交时,会在错误栏下方直接提示相关错误信息。
这便是django表单的一个简单验证功能。
当我填写了一些内容,还未提交直接刷新时,刷新后的界面仍然保留有我已输入的内容(在实际项目中,是提交后,后台可能验证账号不存在等等错误会返回这个界面并且输入的内容仍然存在)。这就是django的一个回显功能。
定制表单
如果刚接触Django表单的话,可能会觉得它很神奇,前端一个 {{ form }} 就能做出一个完整强大的表单。但熟悉了一会后,新鲜劲一过就又会觉得这有什么用?就为了前端省几行代码?耦合性这么高用它干嘛?
使用一种东西就会受制于一种东西,但这并不是django的原意。并非你接收了django表单的方便就要接受这么丑陋的页面。Django表单是可以随你心意定制的:
比如
后台中,我 forms.py 的字段只能用字母下划线作名称,我前端就一定要接受这个名吗?
account = forms.CharField(label='账号',max_length=8)
不但对标签名进行了定制化,还限制了输入的位数,我限制了八位就只能输入八位,第九位是无法输入的。
并非所有的信息都是强制的,根据需要来抉择。
email = forms.EmailField(required=False)
这样一来,即使 email 空着不填,表单也能够正常提交
美化表单
每个表单字段都有一个对应的 Widget class ,它对应一个 HTML 表单 Widget
我们可以使用 Forms 中的 widget 来对我们的前端表单按我们的要求进行改造:
当我们需要一个长文本输入框时:comment = forms.CharField(widget=forms.Textarea)
当我们想做一个下拉框时:
from django.forms.extras.widgets import SelectDateWidget
years = ('2001','2002','2003')
year = forms.DateField(widget=SelectDateWidget(years=years))
对于 ChoiceField字段,Forms默认的是继承select的widget,即使用HTML的列表形式< select > ,而 RadioSelect 使用单选按钮。
如果想要某一个输入框看起来更特别,不一样的话,你可以这样做:
comment = forms.CharField(widget=forms.TextInput(attrs={'size': '40'}))
为其设置attrs,也就是HTML中的css属性。
如果你想要为整个表单或者是更深度的定制一些css以及JavaScript,可以前往Django官方文档了解更多
Forms表单字段
Field.clean(value)
虽然字段类主要使用在表单类中,但你也可以直接实例化它们来使用,以便更好地了解它们是如何工作的。每个字段实例都有一个clean()方法, 它接受一个参数,然后返回“清洁的”数据或者抛出一个django.forms.ValidationError异常:
>>> from django import forms
>>> f = forms.EmailField()
>>> f.clean('foo@example.com')
'foo@example.com'
>>> f.clean('invalid email address')
Traceback (most recent call last):
...
ValidationError: ['Enter a valid email address.']
字段的核心参数
每个字段类的构造函数至少接受这些参数。有些字段类接受额外的、字段特有的参数,但以下参数应该总是能接受:
Field.required
默认情况下,每个字段 类都假设必需有值,所以如果你传递一个空的值 —— 不管是None 还是空字符串(“”) —— clean() 将引发一个ValidationError 异常。
Field.label
正如在前面“输出表单为HTML”中解释的,字段默认label 是通过将字段名中所有的下划线转换成空格并大写第一个字母生成的。如果默认的标签不合适,可以指定label。
>>> from django import forms
>>> class CommentForm(forms.Form):
... name = forms.CharField(label='Your name')
... url = forms.URLField(label='Your Web site', required=False)
... comment = forms.CharField()
>>> f = CommentForm(auto_id=False)
>>> print(f)
<tr><th>Your name:</th><td><input type="text" name="name" /></td></tr>
<tr><th>Your Web site:</th><td><input type="url" name="url" /></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
Field.label_suffix
label_suffix 参数让你基于每个字段覆盖表单的label_suffix。
>>> class ContactForm(forms.Form):
... age = forms.IntegerField()
... nationality = forms.CharField()
... captcha_answer = forms.IntegerField(label='2 + 2', label_suffix=' =')
>>> f = ContactForm(label_suffix='?')
>>> print(f.as_p())
<p><label for="id_age">Age?</label> <input id="id_age" name="age" type="number" /></p>
<p><label for="id_nationality">Nationality?</label> <input id="id_nationality" name="nationality" type="text" /></p>
<p><label for="id_captcha_answer">2 + 2 =</label> <input id="id_captcha_answer" name="captcha_answer" type="number" /></p>
Field.initial
initial 参数让你指定渲染未绑定的表单中的字段时使用的初始值。
Field.widget
widget 参数让你指定渲染表单时使用的Widget 类。更多信息参见Widgets。
Field.help_text
help_text 参数让你指定字段的描述文本。如果提供help_text,在通过表单的便捷方法(例如,as_ul())渲染字段时,它将紧接着字段显示。
Field.error_messages
error_messages 参数让你覆盖字段引发的异常中的默认信息。传递的是一个字典,其键为你想覆盖的错误信息。
Field.validators
validators 参数让你可以为字段提供一个验证函数的列表。
Field.localize
localize 参数启用表单数据的本地化,包括输入和输出。
是否已经改变
Field.has_changed()
has_changed() 方法用于决定字段的值是否从初始值发生了改变。返回True 或False。
内建字段
class BooleanField(**kwargs)
- 默认的Widget:CheckboxInput
- 空值:False
- 规范化为:Python 的True 或 False。
- 如果字段带有required=True,验证值是否为True(例如复选框被勾上)。
- 错误信息的键:required
class CharField(**kwargs)
- 默认的Widget:TextInput
- 空值:’ ‘(一个空字符串)
- 规范化为:一个Unicode 对象。
- 如果提供,验证max_length 或min_length。 否则,所有的输入都是合法的。
- 错误信息的键:required, max_length, min_length
- 可选参数:max_length, min_length
class ChoiceField(**kwargs)
- 默认的Widget:Select
- 空值:”(一个空字符串)
- 规范化为:一个Unicode 对象。
- 验证给定的值在选项列表中存在。
- 错误信息的键:required, invalid_choice
- 可选参数:choices
class TypedChoiceField(**kwargs)
- 默认的Widget:Select
- 空值:empty_value
- 规范化为:coerce 参数类型的值。
- 验证给定的值在选项列表中存在并且可以被强制转换。
- 错误信息的键:required, invalid_choice
- 可选参数:coerce,empty_value
class DateField(**kwargs)
- 默认的Widget:DateInput
- 空值:None
- 规范化为:一个Python datetime.date 对象。
- 验证给出的值是一个datetime.date、datetime.datetime 或指定日期格式的字符串。
- 错误信息的键:required, invalid
- 可选参数:input_formats
class DateTimeField(**kwargs)
- 默认的Widget:DateTimeInput
- 空值:None
- 规范化为:一个Python datetime.datetime 对象。
- 验证给出的值是一个datetime.date、datetime.datetime 或指定日期格式的字符串。
- 错误信息的键:required, invalid
- 可选参数:input_formats
class DecimalField(**kwargs)
- 默认的Widget:当Field.localize 是False 时为NumberInput,否则为TextInput。
- 空值:None
- 规范化为:一个Python decimal。
- 验证给定的值为一个十进制数。忽略前导和尾随的空白。
- 错误信息的键:required, invalid, max_value, min_value, max_digits, max_decimal_places, max_whole_digits
- 四个可选的参数:max_value,min_value,max_digits,decimal_places
class DurationField(**kwargs)
- 默认的Widget:TextInput
- 空值:None
- 规范化为:一个Python timedelta。
- 验证给出的值是一个字符串,而可以给转换为timedelta。
- 错误信息的键:required, invalid.
class EmailField(**kwargs)
- 默认的Widget:EmailInput
- 空值:”(一个空字符串)
- 规范化为:一个Unicode 对象。
- 验证给出的值是一个合法的邮件地址,使用一个适度复杂的正则表达式。
- 错误信息的键:required, invalid
class FileField(**kwargs)
- 默认的Widget:ClearableFileInput
- 空值:None
- 规范化为:一个UploadedFile 对象,它封装文件内容和文件名为一个单独的对象。
- 可以验证非空的文件数据已经绑定到表单。
- 误信息的键:required, invalid, missing, empty, max_length
class FilePathField(**kwargs)
- 默认的Widget:Select
- 空值:None
- 规范化为:一个Unicode 对象。
- 验证选择的选项在选项列表中存在。
- 错误信息的键:required, invalid_choice
- 它接受三个额外的参数;只有path 是必需的:
path,你想要列出的目录的绝对路径。这个目录必须存在。
recursive,如果为False(默认值),只用直接位于path 下的文件或目录作为选项。如果为True,将递归访问这个目录,其所有的子目录和文件都将作为选项。
match,正则表达式表示的一个模式;只有匹配这个表达式的名称才允许作为选项。
allow_files,可选。为True 或False。默认为True。表示是否应该包含指定位置的文件。它和allow_folders 必须有一个为True。
allow_folders,可选。为True 或False。 默认为False。表示是否应该包含指定位置的目录。 它和allow_files 必须有一个为True。
class FloatField(**kwargs)
- 默认的Widget:当 Field.localize 是False 时为NumberInput,否则为TextInput。
- 空值:None
- 规范化为:一个Float 对象。
- 验证给出的值是一个浮点数。和Python 的float() 函数一样,允许前导和尾随的空白符。
- 错误信息的键:required, invalid, max_value, min_value
class ImageField(**kwargs)
- 默认的Widget:ClearableFileInput
- 空值:None
- 规范化为: An UploadedFile object that wraps the file content and file name into a single object.
- 验证文件数据已绑定到表单,并且该文件具有Pillow理解的图像格式。
- 错误信息的键:required, invalid, missing, empty, invalid_image
class IntegerField(**kwargs)
- 默认的Widget:当Field.localize 是False 时为NumberInput,否则为TextInput。
- 空值:None
- 规范化为:一个Python 整数或长整数。
- 验证给定值是一个整数。允许前导和尾随空格,如Python的int()函数。
- 错误信息的键:required, invalid, max_value, min_value
- 可选参数:max_value,min_value
class GenericIPAddressField(**kwargs)
包含IPv4或IPv6地址的字段。
- 默认的Widget:TextInput
- 空值:”(一个空字符串)
- 规范化为:一个Unicode 对象。 IPv6地址如下所述进行归一化。
- 验证给定值是有效的IP地址。
- 错误信息的键:required, invalid
- 可选参数:protocol,unpack_ipv4
class MultipleChoiceField(**kwargs)
- 默认的Widget:SelectMultiple
- 空值:[](一个空列表)
- 规范化为:一个Unicode 对象列表。
- 验证给定值列表中的每个值都存在于选择列表中。
- 错误信息的键:required, invalid_choice, invalid_list
class TypedMultipleChoiceField(**kwargs)
就像MultipleChoiceField,除了TypedMultipleChoiceField需要两个额外的参数,coerce和empty_value。
- 默认的Widget:SelectMultiple
- 空值:empty_value
- 规范化为:coerce参数提供的类型值列表。
- 验证给定值存在于选项列表中并且可以强制。
- 错误信息的键:required, invalid_choice
class NullBooleanField(**kwargs)
- 默认的Widget:NullBooleanSelect
- 空值:None
- 规范化为:一个Python True, False 或None 值。
- 不验证任何内容(即,它从不引发ValidationError)。
class RegexField(**kwargs)
- 默认的Widget:TextInput
- 空值:”(一个空字符串)
- 规范化为:一个Unicode对象
- 验证给定值与某个正则表达式匹配。
- 错误信息的键:required, invalid
class SlugField(**kwargs)
- 默认的Widget:TextInput
- 空值:None
- 规范化为:一个Python 的datetime.time 对象。
- 验证给定值是datetime.time或以特定时间格式格式化的字符串。
- 错误信息的键:required, invalid
class TimeField(**kwargs)
- 默认的Widget:TextInput
- 空值:None
- 规范化为:一个Python 的datetime.time 对象。
- 验证给定值是datetime.time或以特定时间格式格式化的字符串。
- 错误信息的键:required, invalid
class URLField(**kwargs)
- 默认的Widget:URLInput
- 空值:”(一个空字符串)
- 规范化为:一个Unicode 对象。
- 验证给定值是有效的URL。
- 错误信息的键:required, invalid
class UUIDField(**kwargs)
- 默认的Widget:TextInput
- 空值:”(一个空字符串)
- 规范化为:一个UUID 对象。
- 错误信息的键:required, invalid
- 复杂点的内建Field类
class ComboField(**kwargs)
- 默认的Widget:TextInput
- 空值:”(一个空字符串)
- 规范化为:一个Unicode 对象。
- 根据指定为ComboField的参数的每个字段验证给定值。
- 错误信息的键:required, invalid
class MultiValueField(fields=(), **kwargs)
- 默认的Widget:TextInput
- 空值:”(一个空字符串)
- 规范化为:子类的compress方法返回的类型。
- 针对指定为MultiValueField的参数的每个字段验证给定值。
- 错误信息的键:required, invalid, incomplete
class SplitDateTimeField(**kwargs)
- 默认的Widget:SplitDateTimeWidget
- 空值:None
- 规范化为:一个Python datetime.datetime 对象。
- 验证给定的值是datetime.datetime或以特定日期时间格式格式化的字符串。
- 错误信息的键:required, invalid, invalid_date, invalid_time
- 处理关系的字段
两个字段可用于表示模型之间的关系:ModelChoiceField和ModelMultipleChoiceField。这两个字段都需要单个queryset参数,用于创建字段的选择。在表单验证时,这些字段将把一个模型对象(在ModelChoiceField的情况下)或多个模型对象(在ModelMultipleChoiceField的情况下)放置到cleaned_data表单的字典。
对于更复杂的用法,可以在声明表单字段时指定queryset=None,然后在窗体的init()方法中填充queryset:
class FooMultipleChoiceForm(forms.Form):
foo_select = forms.ModelMultipleChoiceField(queryset=None)
def __init__(self, *args, **kwargs):
super(FooMultipleChoiceForm, self).__init__(*args, **kwargs)
self.fields['foo_select'].queryset = ...
class ModelChoiceField(**kwargs)
- 默认的Widget:Select
- 空值:None
- 规范化为:一个模型实例。
- 验证给定的id存在于查询集中。
- 错误信息的键:required, invalid_choice
class ModelMultipleChoiceField(**kwargs)
- 默认的Widget:SelectMultiple
- 空值:QuerySet (self.queryset.none())
- 规范化为: 模型实例的一个QuerySet。
- 验证在给定的值列表中的每个id存在于查询集中。
- 错误信息的键:required, list, invalid_choice, invalid_pk_value
- 创建自定义的字段
如果内建的字段不能满足你的需求,你可以很容易地创建自定义的字段。你需要创建django.forms.Field 的一个子类。它只要求实现一个clean() 方法和接收上面核心参数的init() 方法(required, label, initial, widget, help_text)。