目录

    1. 自动生成HTML表单元素

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

    • 指定小部件 `python from django import forms

    class CommentForm(forms.Form): name = forms.CharField() url = forms.URLField() comment = forms.CharField(widget=forms.Textarea)

    CommentForm().as\_table()输出值
    ```html
    <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 小部件。

    • 自定义小部件的样式
    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() 输出值

    <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 ,然后传入模板。
      from django.shortcuts import render
      from .forms import CommentForm
        pass
        form = CommentForm()
        return render(request, 'my_template.html', {'form': form})
      
      在模板中使用,my_template.html。根据,所有的表单字段和属性,将通过 Django 的模板语言拆分成 HTML 标记 。
      <form action="/my_template_data/" method="post">
        {% csrf_token %}
        {{ form }}
        <input type="submit" value="Submit" />
      </form>
      

    可选的表单渲染项:

    以表格的形式将它们渲染在tr标签中

    将它们渲染在p 标签中

    将它们渲染在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

    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

    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

    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')  #只显示model中指定的字段
    

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