1. 自动生成HTML表单元素
Widget,用来渲染成HTML元素的工具。
|
| 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 小部件。
|
| 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 ,然后传入模板。
|
| 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 标记 。
|
| <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
|
| 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) | | | | email = forms.EmailField(validators=[validate_email]) | | | | 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) | | | | 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
|
| from django.db import models | | class Contact(models.Model): | | title = models.CharField(max_length=30) | | content = models.CharField(max_length=20) |
|
form.py
|
| from django.forms import ModelForm | | from .models import Contact | | class ConotactForm(ModelForm): | | class Meta: | | model = Contact | | field = ('title','content') |
|
Form 只需要继承 ModelForm 类,并在 Meta 中指定映射的 Model,Django Forms 会自动在 Form 中添加 field 指定的字段。而不需要,像继承 forms.Form ,一个字段一个字段添加。