Django学习(六):表单

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

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


构建一个简单表单的流程

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文件中使用表单模板

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

注:为了上传文件,需要确保<form>元素正确定义enctype 为"multipart/form-data" :

<form enctype="multipart/form-data" method="post" action="/foo/">
</form>

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


窗口小部件(Widget)

每个表单字段都有一个对应的Widget 类,它对应一个HTML 表单部件,如<input type="text">

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

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

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


内置小部件有:

TextInput -->呈现为:<input type =“text” ...>
PasswordInput -->呈现为:<input type =“password” ...>

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

Textarea -->呈现为:<textarea>...</textarea>

DateInput/DateTimeInput /TimeInput  -->呈现为:<input type =“text” ...>;接收的参数与TextInput 相同,但是带有一些可选的参数,如format

EmailInput -->呈现为:<input type =“email” ...>
URLInput -->呈现为:<input type =“url” ...>

HiddenInput -->呈现为:<input type =“hidden” ...>

Textarea -->呈现为:<textarea>...</textarea>

DateInput/DateTimeInput /TimeInput  -->呈现为:<input type =“text” ...>;接收的参数与TextInput 相同,但是带有一些可选的参数,如format

CheckboxInput -->呈现为:<input type="checkbox" ...>;可选参数 check_test
Select -->呈现为: <select><option ...>...</select>;属性  choices
SelectMultiple -->允许多个选择:<select multiple="multiple">...</select>
RadioSelect -->呈现为:<ul><li><input type="radio" name="..."></li>...</ul>

FileInput -->呈现为:<input type="file" ...>
ClearableFileInput -->呈现为:<input type =“file” ...> 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> 标签中;为了给每个Form一个自己的命名空间,可以使用prefix 关键字参数


表单模板

输出选项:必须自己提供<ul> 或<table> 元素,还有</form> 和<form> 以及<input type="submit"> 标签
{{ form.as_table }} 以表格的形式将它们渲染在<tr> 标签中
{{ form.as_p }} 将它们渲染在<p> 标签中

{{ form.as_ul }} 将它们渲染在<li> 标签中

手动渲染字段,举例:

<div class="fieldWrapper">
    {{ form.message.errors }}
    <label for="{{ form.message.id_for_label }}">Your message:</label>
    {{ form.message }}
</div>

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

{{ field }} 中的属性:

{{ field.label }} -->字段的label名
{{ field.label_tag }} -->包含在HTML <label> 标签中的字段Label
{{ field.id_for_label }} -->用于这个字段的ID

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

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

{ field.help_text }} -->与该字段关联的帮助文档。
{{ field.errors }}-->输出一个<ul class="errorlist">,包含这个字段的验证错误信息

{{ 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_ <fieldname>()方法 。 这个方法用于特定属性值相关的验证,这个验证与字段的类型无关。此方法的返回值将替换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而来。



猜你喜欢

转载自blog.csdn.net/hua1011161696/article/details/80933324
今日推荐