Django 的 Form 类提供了一系列生成表单的功能,免去手动维护表单的麻烦。

基础

创建一个表单

forms.py

from django import forms

class NameForm(forms.Form):
    your_name = forms.CharField(label='Your name', max_length=100)

上述代码定义了单字段表单,CharFiled 代表字段接受的数据类型为文本,参数 label 代表生成标签中的文件,max_length 用以表单验证限制字段的最大数据长度。

每个 Form 实例都有一个 is_valid() 方法用以常规验证表单数据,调用该方法时,如果所有内容验证通过,则返回 True,同时将所有数据放入 cleaned_data 属性中。

上面表单渲染结果类似:

<label for="your_name">Your name: </label>
<input id="your_name" type="text" name="your_name" maxlength="100" required />

注意:使用表单类生成的表单并不包含 <form>提交csrf 标签,使用时需自行添加。

视图部分

from django.shortcuts import render
from django.http import HttpResponseRedirect

from .forms import NameForm

def get_name(request):
    # 如果是 POST 请求则处理表单数据
    if request.method == 'POST':
        # 创建表单实例并使用请求数据填充该表单
        form = NameForm(request.POST)
        # 表单验证
        if form.is_valid():
            # process the data in form.cleaned_data as required
            # ...
            # redirect to a new URL:
            return HttpResponseRedirect('/thanks/')

    # 如果是 GET 或其他类型请求则渲染空白表单
    else:
        form = NameForm()

    return render(request, 'name.html', {'form': form})

模板部分

name.html

<form action="/your-name/" method="post">
    {% csrf_token %}
    {{ form }}
    <input type="submit" value="Submit" />
</form>

绑定与未绑定数据的表单

Django Form 如果绑定了一组数据就成为绑定数据的表单,反之为未绑定数据的表单。绑定数据的表单可以用作表单验证,而且可以将带有数据的表单渲染到 HTML 中。未绑定数据的表单用作渲染空白的表单到页面。

未绑定数据表单实例

>>> f = ContactForm()

绑定数据的表单

将数据以字典的形式传入 Form 类构造器即可:

>>> data = {'subject': 'hello',
...         'message': 'Hi there',
...         'sender': 'foo@example.com',
...         'cc_myself': True}
>>> f = ContactForm(data)

传入表单类的字典 key 为与表单相对应的字段名,value 为相应的值。

绑定数据表单注意

  • 可以使用 is_bound() 检查表单是否绑定了数据。
  • 传入空字典 {} 到表单对象,该表单也会被视为绑定数据表单。
  • 无法修改已绑定到表单中的数据,但可以通过创建新表单实现数据的修改。

动态初始化表单值

在表单对象中通过 initial 参数传入一个字典,即可在页面渲染时为表单字段设置相应的初始值。

>>> f = ContactForm(initial={'subject': 'Hi there!'})

表单字段

官方文档:https://docs.djangoproject.com/en/2.0/ref/forms/fields/

Field.clean(value)
用以对表单提交的值进行常规验证

>>> from django import forms
>>> f = forms.EmailField()
>>> f.clean('foo@example.com')
'foo@example.com'
>>> f.clean('invalid email address')
Traceback (most recent call last):
...
ValidationError: ['Enter a valid email address.']

核心的字段参数

每个 Filed 类构造器都需要至少 3 个参数,一些字段类型还接受额外的参数和设置。

required
除非指定 required=False,否则任何构造的字段均为必填。

label
默认会使用字段变量名的大写首字母形式作为 label 标签值,也可以手动指定 label='Your_Label'

label_suffix
指定 label 值的后缀,比如 label_suffix=' :'

initial
指定字段的初始值,例如 initial='https://

help_text
指定字段的帮助文本,一般显示在字段的下方,例如 help_text='最多允许100个字'

error_messages
覆盖默认的表单验证信息,必须使用字典,例如 error_messages={'required': '姓名必须填写'}

validators
允许指定一系列验证方法,参考文档

disabled
禁用该表单项,例如 disabled=True

可用字段

BooleanField
布尔值,对应 CheckboxInput,必须指定 required=False

CharField
文本框,表单验证参数 max_lengthmin_lengthstrip 默认为 True 即自动去除文本前后的空白字符。

ChoiceField
多选

DateField
日期,参数 input_formats 格式化日期

DateTimeField
日期时间,参数 input_formats 格式化日期

字段数据

无论表单提交的数据是什么类型,只要通过了 is_valid() 方法的验证,即返回 True。那么表单数据就会被存储 form.cleaned_data 字典当中。

当然可以使用 request.POST['username'] 使用原生的表单数据,但使用干净的 form.cleaned_data['username'] 更好。

手动渲染字段

任何表单字段都可以使用格式为 {{ form.name_of_field }} 的标签在模板中渲染,例如:

{{ form.non_field_errors }}
<div class="fieldWrapper">
    {{ form.subject.errors }}
    <label for="{{ form.subject.id_for_label }}">Email subject:</label>
    {{ form.subject }}
</div>
<div class="fieldWrapper">
    {{ form.message.errors }}
    <label for="{{ form.message.id_for_label }}">Your message:</label>
    {{ form.message }}
</div>
<div class="fieldWrapper">
    {{ form.sender.errors }}
    <label for="{{ form.sender.id_for_label }}">Your email address:</label>
    {{ form.sender }}
</div>
<div class="fieldWrapper">
    {{ form.cc_myself.errors }}
    <label for="{{ form.cc_myself.id_for_label }}">CC yourself?</label>
    {{ form.cc_myself }}
</div>

完整的 label 标签可以使用 label_tag() 方法生成,例如:

<div class="fieldWrapper">
    {{ form.subject.errors }}
    {{ form.subject.label_tag }}
    {{ form.subject }}
</div>

显示错误信息

在模板中使用 {{ form.non_field_errors }} 标签,会渲染出未排序的错误并列表:

<ul class="errorlist">
    <li>Sender is required.</li>
</ul>

迭代表单字段

{% for field in form %}
    <div class="fieldWrapper">
        {{ field.errors }}
        {{ field.label_tag }} {{ field }}
        {% if field.help_text %}
        <p class="help">{{ field.help_text|safe }}</p>
        {% endif %}
    </div>
{% endfor %}