Django学习(六):表单

表单系统的核心部分是Django 的Form 类;Form 类描述一个表单并决定它如何工作和展现。

就像模型类的属性映射到数据库的字段一样,表单类的字段会映射到HTML 的表单元素(或其它表单元素)


构建一个简单表单的流程

1,在form.py中定义表单类

from django import forms

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

2,在views.py中实例化表单与处理表单数据

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():
            # 在需要时,可以在form.cleaned_date中处理数据
            # ...
            # 重定向到一个新的URL:
            return HttpResponseRedirect('/thanks/')

    # 如果是GET或者其它请求方法,我们将创建一个空的表单。
    else:
        form = NameForm()

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

3,在html文件中使用表单模板

{% csrf_token %} {{ form }}

注:为了上传文件,需要确保

元素正确定义enctype 为"multipart/form-data" :


实例化表单类时:
>>> f = ContactFormWithMugshot(request.POST, request.FILES)


窗口小部件(Widget)

每个表单字段都有一个对应的Widget 类,它对应一个HTML 表单部件,如

在大部分情况下,字段都具有一个合理的默认Widget。 例如,默认情况下,CharField 具有一个TextInput Widget,它在HTML 中生成一个

Widget 负责渲染HTML和提取GET/POST 字典中的数据。

注:由内置小部件生成的HTML使用HTML5语法;它使用布尔属性,如checked,而不是checked='checked'的XHTML样式


内置小部件有:

TextInput -->呈现为:
PasswordInput -->呈现为:

接收一个可选的参数:render_value; 决定在验证错误后重新显示表单时,Widget 是否填充(默认为False)

Textarea -->呈现为:

DateInput/DateTimeInput /TimeInput  -->呈现为:;接收的参数与TextInput 相同,但是带有一些可选的参数,如format

EmailInput -->呈现为:
URLInput -->呈现为:

HiddenInput -->呈现为:

Textarea -->呈现为:

DateInput/DateTimeInput /TimeInput  -->呈现为:;接收的参数与TextInput 相同,但是带有一些可选的参数,如format

CheckboxInput -->呈现为:;可选参数 check_test
Select -->呈现为: ;属性  choices
SelectMultiple -->允许多个选择:
RadioSelect -->呈现为:

  • ...

FileInput -->呈现为:
ClearableFileInput -->呈现为: with an additional checkbox input to clear the field’s value, if the field is not required and has initial data.


内建字段类

注:所有的Field子类都默认带有required=True

一个表单的字段本身就是类;他们管理表单数据,并在提交表单时执行验证。

1,BooleanField--> class BooleanField(**kwargs)
默认的Widget:CheckboxInput
规范化为:Python 的True 或 False。
错误信息的键:required

2,CharField -->class CharField(**kwargs)
默认的Widget:TextInput
错误信息的键:min_length, max_length, required

参数:max_length/min_length,确保字符串的最大和最小长度;strip,(默认为True)该值将被剥离前导和尾随空格。

3,ChoiceField
默认的Widget:Select
可选参数:choices,用来作为该字段选项的一个二元组组成的可迭代对象(例如,列表或元组)或者一个可调用对象

错误信息的键:required, invalid_choice

4,DateField -->class DateField(**kwargs)
默认的Widget:DateInput
规范化为:一个Python datetime.date 对象
错误信息的键:required, invalid

可选参数:input_formats,一个格式的列表,用于转换一个字符串为datetime.date 对象

#默认输入格式为:
['%Y-%m-%d',      # '2006-10-25'
 '%m/%d/%Y',      # '10/25/2006'
 '%m/%d/%y']      # '10/25/06'
5,DateTimeField
默认的Widget:DateTimeInput
规范化为:一个Python datetime.datetime 对象
错误信息的键:required, invalid

可选参数:input_formats,一个格式的列表,用于转换一个字符串为datetime.datetime 对象

#默认输入格式为:
['%Y-%m-%d %H:%M:%S',    # '2006-10-25 14:30:59'
 '%Y-%m-%d %H:%M',       # '2006-10-25 14:30'
 '%Y-%m-%d',             # '2006-10-25'
 '%m/%d/%Y %H:%M:%S',    # '10/25/2006 14:30:59'
 '%m/%d/%Y %H:%M',       # '10/25/2006 14:30'
 '%m/%d/%Y',             # '10/25/2006'
 '%m/%d/%y %H:%M:%S',    # '10/25/06 14:30:59'
 '%m/%d/%y %H:%M',       # '10/25/06 14:30'
 '%m/%d/%y']             # '10/25/06'
6,TimeField
默认的Widget:TextInput
规范化为:一个Python 的datetime.time 对象
错误信息的键:required, invalid
可选参数:input_formats,用于尝试将字符串转换为有效的datetime.time对象的格式列表。
#默认输入格式为:
'%H:%M:%S',     # '14:30:59'
'%H:%M',        # '14:30'
7,DecimalField
默认的Widget:当Field.localize 是False 时为NumberInput,否则为TextInput。
规范化为:一个Python decimal
错误信息的键:max_whole_digits, max_digits, max_decimal_places, max_value, invalid, required, min_value
可选参数:
max_value/min_value,控制字段中允许的值的范围,应该以decimal.Decimal 值给出;

max_digits,值允许的最大位数 ; decimal_places,允许的最大小数位


8,FloatField
默认的Widget:当Field.localize 是False 时为NumberInput,否则为TextInput
规范化为:一个Float 对象
错误信息的键:max_value, invalid, required, min_value
可选参数:max_value/min_value,控制字段中允许的值的范围

9,IntegerField
默认的Widget:当Field.localize 是False 时为NumberInput,否则为TextInput。
规范化为:一个Python 整数或长整数
错误信息的键:max_value, invalid, required, min_value
可选参数:max_value/min_value,控制字段中允许的值的范围

10,EmailField
默认的Widget:EmailInput
错误信息的键:required, invalid
验证给出的值是一个合法的邮件地址,使用一个适度复杂的正则表达式

11,MultipleChoiceField
默认的Widget:SelectMultiple

错误信息的键:invalid_list, invalid_choice, required

12,FileField
默认的Widget:ClearableFileInput
规范化为:一个UploadedFile 对象,它封装文件内容和文件名为一个单独的对象
错误信息的键:missing, invalid, required, empty, max_length

可选参数:max_length,文件名的最大长度 ;allow_empty_file,允许文件内容为空。

13,ImageField
默认的Widget:ClearableFileInput
规范化为:一个UploadedFile 对象,它封装文件内容和文件名为一个单独的对象
错误信息的键:missing, invalid, required, empty, invalid_image
验证文件数据已绑定到表单,并且该文件具有Pillow理解的图像格式;

注:使用ImageField需要安装Pillow并支持您使用的图像格式。


核心字段参数

required-->表示字段的值不能为空;默认值为required = True
label -->该参数可让你指定字段“对人类友好”的标签
label_suffix -->设置标签后缀
initial -->指定渲染未绑定的字段的初始值

注:如果某个字段的值没有给出,initial 值不会作为“后备”的数据;initial 值只用于原始表单的显示

widget --> 指定渲染Widget时使用的widget 类
error_messages -->覆盖字段引发的异常中的默认信息。 传递的是一个字典,其键为想覆盖的错误信息
validators -->可以为字段提供一个验证函数的列表

help_text -->指定Field的描述文本
localize -->可以实现表单数据输入的定位,以及渲染输出

disabled -->当设置为True时,禁用表单域,以使用户无法编辑


Forms API

Form.is_bound-->是绑定表单则返回True
不包含数据的表单称为未绑定表单,当render给用户时,它将为空或包含默认的值;
包含数据的表单称为绑定表单,因此可以用来检验数据是否合法。

注:传递一个空的字典将创建一个带有空数据的绑定的表单,如 f = ContactForm({})

Form.errors -->获得错误信息的一个字典;错误信息保存在列表中是因为字段可能有多个错误信息

Form.clean()-->当需要为相互依赖的字段添加自定义的验证时,可以重写Form的clean()方法。

Form.non_field_errors() -->返回Form.errors 中不是与特定字段相关联的错误

Form.is_valid()-->验证数据,返回一个表示数据是否合法的布尔值

Form.cleaned_data-->保存验证后(通过is_valid() 成功验证)的表单数据的一个字典;字典中只包含合法的字段,只包含Form中定义的字段

Form.has_changed() -->检查表单的数据是否从初始数据发生改变

Form.changed_data-->返回一个包含那些在表单的绑定数据中的值(通常为request.POST)与原始值发生改变的字段的名字列表

Form.fields -->访问表单中的字段
>>> for row in f.fields.values(): print(row)

>>> f.fields['name']

Form.error_css_class / Form.required_css_class
Form类具有上面这一对钩子,可以使用它们来添加class 属性给必填的行或有错误的行

Form.initial -->动态初始值
>>> f = ContactForm(initial={'subject': 'Hi there!'})
这些值只显示在没有绑定的表单中,即使没有提供特定值它们也不会作为后备的值。

Form.auto_id -->id 和label 的行为使用Form构造函数的auto_id 参数控制。 这个参数必须为True、False 或者一个字符串。
默认情况下,auto_id 设置为'id_%s';
auto_id =True :有lable和id,此时id的值为Form类中的字段名,有空格的会改为_
auto_id =False :没有lable标签和id属性

Form.label_suffix -->定义标签后缀,默认为 :(英文版)

Form.prefix -->可以将几个Django Form放在一个

标签中;为了给每个Form一个自己的命名空间,可以使用prefix 关键字参数


表单模板

输出选项:必须自己提供

    或 元素,还有 和 以及 标签
    {{ form.as_table }} 以表格的形式将它们渲染在 标签中
    {{ form.as_p }} 将它们渲染在

    标签中

    {{ form.as_ul }} 将它们渲染在

  • 标签中

    手动渲染字段,举例:

    {{ form.message.errors }} {{ form.message }}

    {{ form.subject.errors }} {{ form.subject.label_tag }} {{ form.subject }}

    {{ field }} 中的属性:

    {{ field.label }} -->字段的label名
    {{ field.label_tag }} -->包含在HTML

    {{ field.value }} -->字段的值

    {{ field.html_name }} -->输入元素的name 属性中将使用的名称

    { field.help_text }} -->与该字段关联的帮助文档。
    {{ field.errors }}-->输出一个

      ,包含这个字段的验证错误信息

      {{ field.is_hidden }} -->如果字段是隐藏字段,则为True。

      {{ field.field }} -->表单类中的Field 实例,可以使用它来访问Field属性,例如{{ char_field.field.max_length }}


      表单和字段验证

      表单验证发生在数据验证之后;所有以下验证方法都可以抛出ValidationError

      表单验证步骤:

      1,Field上的to_python()方法验证,它强制该值转为正确的数据类型,或者引发ValidationError。这个方法从Widget 接收原始的值并返回转换后的值

      2,Field上的validate()方法处理不适合验证器验证的特定字段。在任何错误上会引发ValidationError;当遇到不可以或不想放在验证器中的验证逻辑时,应该覆盖它来处理验证。

      3,Field上的run_validators()方法运行所有字段的验证器,并将所有错误聚合到单个ValidationError中。 不应该重写此方法。

      4,Field子类上的clean()方法负责以正确的顺序运行to_python(),validate()和run_validators()并传播它们的错误。 此方法返回 clean data,然后将其插入到表单的cleaned_data字典中。

      5,在Form子类上调用clean_ ()方法 。 这个方法用于特定属性值相关的验证,这个验证与字段的类型无关。此方法的返回值将替换cleaned_data中的现有值。

      6,表单子类的clean()方法可以执行需要访问多个表单字段的验证。 如“如果提供了字段A,则字段B必须包含有效的电子邮件地址”。 如果愿意,此方法可以返回完全不同的字典,该字典将作为cleaning_data。

      注:Form.clean()引发的任何错误都不会与任何字段相关联。 它们位于一个特殊的“字段”(称为__all__),如果需要,可以通过non_field_errors()方法访问它。 如果要将错误附加到表单中的特定字段,则需要调用add_error()。


      抛出异常规范写法:

      #抛出一个异常(规范写法!)
      raise ValidationError(
          _('Invalid value: %(value)s'),
          code='invalid',
          params={'value': '42'},
      )
      
      
      #同时抛出多个异常
      raise ValidationError([
          ValidationError(_('Error 1'), code='error1'),
          ValidationError(_('Error 2'), code='error2'),
      ])

      内置验证器:

      class RegexValidator(regex=None, message=None, code=None, inverse_match=None, flags=0)
      参数:
      regex-->进行匹配的正则表达式
      message-->验证失败时ValidationError所使用的错误信息。 默认为"Enter a valid value"。
      code-->验证失败时ValidationError所使用的错误代码。 默认为"invalid"。
      inverse_match-->regex的匹配模式。 默认为False。为True时,则正则匹配上时抛出 ValidationError异常

      flags-->编译正则表达式字符串regex时所用的标识,默认为 0


      class EmailValidator(message=None, code=None, whitelist=None)
      message-->验证失败时ValidationError所使用的错误信息。 默认为"Enter a valid email address"。
      code-->验证失败时ValidationError所使用的错误代码。  默认为"invalid"。
      whitelist-->所允许的邮件域名的白名单


      自定义验证器:

      #定义验证器
      def validate_even(value):
          if value % 2 != 0:
              raise ValidationError(
                  _('%(value)s is not an even number'),
                  params={'value': value},
              )
      
      #在模型中使用
      class MyModel(models.Model):
          even_field = models.IntegerField(validators=[validate_even])
      
      #在表单中使用
      class MyForm(forms.Form):
          even_field = forms.IntegerField(validators=[validate_even])

      模型和表单

      实际上,如果你的表单打算直接用来添加和编辑Django 的模型,ModelForm 可以节省你的许多时间、精力和代码,因为它将根据Model 类构建一个表单以及适当的字段和属性。

      class ModelForm:

      Django 提供的一个辅助类,让你可以从Django 的模型创建与该模型紧密映射的表单Form。

      示例:

      from django.forms import ModelForm
      from myapp.models import Article
      
      
      class ArticleForm(ModelForm):
           class Meta:
               model = Article
               fields = ['pub_date', 'headline', 'content', 'reporter']


      生成的Form类中将具有和指定的模型字段对应的表单字段,顺序为fields 属性中指定的顺序。

      每个模型字段有一个对应的默认表单字段:
      模型字段 CharField --> 表单字段 CharField
      ForeignKey --> ModelChoiceField

      ManyToManyField --> ModelMultipleChoiceField


      如果模型字段设置了blank=True,那么表单字段的required字段会设置为False值。 否则,required=True。
      表单字段的label 设置为模型字段的verbose_name,并将第一个字母大写。
      如果模型字段设置了choices,那么表单字段的widget将会设置为Select,选择项从模型字段的choices而来。



      你可能感兴趣的:(Django学习(六):表单)