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 id="id_name" name="name" type="text" /></td></tr>\n<tr><th><label for="id_url">Url:</label></th><td><input id="id_url" name="url" type="url" /></td></tr>\n<tr><th><label for="id_comment">Comment:</label></th><td><textarea cols="40" id="id_comment" 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 class="special" id="id_name" name="name" type="text" /></td></tr>\n<tr><th><label for="id_url">Url:</label></th><td><input id="id_url" name="url" type="url" /></td></tr>\n<tr><th><label for="id_comment">Comment:</label></th><td><input id="id_comment" 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。否则,返回错误提示。
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’…能满足绝大多数的场景。
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 ,一个字段一个字段添加。