Django Forms 功能

1. 自动生成HTML表单元素

Widget,用来渲染成HTML元素的工具。

  • 指定小部件
1
2
3
4
5
6
from django import forms
class CommentForm(forms.Form):
name = forms.CharField()
url = forms.URLField()
comment = forms.CharField(widget=forms.Textarea)

CommentForm().as_table() 输出值

1
<tr><th><label for="id_name">Name:</label></th><td><input   name="name" type="text" /></td></tr>\n<tr><th><label for="id_url">Url:</label></th><td><input   name="url" type="url" /></td></tr>\n<tr><th><label for="id_comment">Comment:</label></th><td><textarea cols="40"   name="comment" rows="10">\r\n</textarea></td></tr>

指定表单字段为 Textarea 小部件,而不是默认的 TextInput 小部件。

  • 自定义小部件的样式
1
2
3
4
class CommentFormClass(forms.Form):
name = forms.CharField(widget=forms.TextInput(attrs={'class': 'special'}))
url = forms.URLField()
comment = forms.CharField(widget=forms.TextInput(attrs={'size': '40'}))

CommentFormClass().as_table() 输出值

1
<tr><th><label for="id_name">Name:</label></th><td><input     name="name" type="text" /></td></tr>\n<tr><th><label for="id_url">Url:</label></th><td><input   name="url" type="url" /></td></tr>\n<tr><th><label for="id_comment">Comment:</label></th><td><input   name="comment" size="40" type="text" /></td></tr>
  • 输出形式

通常我们在 views.py 函数中,实例化 Form ,然后传入模板。

1
2
3
4
5
from django.shortcuts import render
from .forms import CommentForm
pass
form = CommentForm()
return render(request, 'my_template.html', {'form': form})

在模板中使用,my_template.html 。根据 {{ form }},所有的表单字段和属性,将通过 Django 的模板语言拆分成 HTML 标记 。

1
2
3
4
5
<form action="/my_template_data/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</form>

可选的表单渲染项:{{ form.as_table }} 以表格的形式将它们渲染在tr标签中{{ form.as_p }} 将它们渲染在p 标签中{{ form.as_ul }} 将它们渲染在ul标签中

2. 检查表单数据的合法性

为了能够快速、有效的校验提交的数据。Django Forms提供了对表单数据合法性校验的支持。校验流程

  • 继承 form.Form ,创建自定义 Form 类 MyForm
  • 使用 request.POST,实例化 MyForm类
  • 合法性校验,is_valid()
  • 获取合法数据或返回错误提示

下面是一个简单的例子:forms.py

1
2
3
from django import forms
class Contact(forms.Form):
email = forms.EmailField(error_messages={'required':u'邮箱不能为空'})

views.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from django.http import HttpResponse
from .forms import Contact
def my_view(request):
form = Contact(request.POST)
if not form.is_valid():
return HttpResponse(
json.dumps({
"result": False,
"data": [],
"message": form.errors,
"code": -1
}), content_type='application/json')
else:
return HttpResponse(
json.dumps({
"result": True,
"data": [],
"message": form.cleaned_data.get('email'),
"code": -1
}), content_type='application/json')

如果接口从POST数据中,获取到了email字段,并且为邮箱字段,就返回True。否则,返回错误提示。

2.1 继承 Form

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import re
from django import forms
from django.core.validators import validate_email
from django.core.exceptions import ValidationError
class ContactForm(forms.Form):
cn8_re = re.compile(ur'^[-_\w\u4e00-\u9fa5]{3,16}$')
SEXUAL_CHOICES = (
(0, u'男'),
(1, u'女')
)
# 正则校验
nick_name = forms.RegexField(min_length=3, max_length=16, label=u'昵称',
error_messages={
'required': u'昵称不能为空,长度3~16中英文及_-',
'invalid': u'请输入合法昵称(3~16位以内中英文字符).'
}, regex=cn8_re)
# 指定函数校验validate_email,可以指定多个
email = forms.EmailField(validators=[validate_email])
# 指定为Choice
gender = forms.ChoiceField(choices=SEXUAL_CHOICES, required=False, label=u'性别')
# 指定长度
password_0 = forms.RegexField(min_length=8, max_length=20, label=u'密码',
error_messages=''egex=pwd_regex)
password_1 = forms.RegexField(min_length=8, max_length=20, label=u'确认密码',
error_messages='pwd_error_msg', regex=pwd_regex)
# 重载clean函数,实现自定义的校验
def clean(self):
if self.cleaned_data.get('password_0') != self.cleaned_data.get('password_1'):
self.add_error('password_1', u"两次密码输入不匹配.")
raise ValidationError(u"两次密码输入不匹配.")
return self.cleaned_data

Django Forms提供了大量的Field用于数据有效性校验, ‘Field’, ‘CharField’, ‘IntegerField’, ‘DateField’, ‘TimeField’, ‘DateTimeField’, ‘DurationField’, ‘RegexField’, ‘EmailField’, ‘FileField’, ‘ImageField’, ‘URLField’, ‘BooleanField’&mldr;能满足绝大多数的场景。

2.2 结合Model

如果 POST 提交的数据,是为了操作 Model 数据,为什么不能简单点,直接用 Model 初始化 Form 的字段呢?当然可以。models.py

1
2
3
4
from django.db import models
class Contact(models.Model):
title = models.CharField(max_length=30)
content = models.CharField(max_length=20)

form.py

1
2
3
4
5
6
from django.forms import ModelForm
from .models import Contact
class ConotactForm(ModelForm):
class Meta:
model = Contact
field = ('title','content') #只显示model中指定的字段

Form 只需要继承 ModelForm 类,并在 Meta 中指定映射的 Model,Django Forms 会自动在 Form 中添加 field 指定的字段。而不需要,像继承 forms.Form ,一个字段一个字段添加。