Please enable Javascript to view the contents

Django Forms 功能

 ·  ☕ 3 分钟

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。否则,返回错误提示。

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’…能满足绝大多数的场景。

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 ,一个字段一个字段添加。


微信公众号
作者
微信公众号