【20.1】Django框架Form组件之常用字段及插件

【零】引入

  • 创建Form类时主要涉及到 【字段】 和 【插件】
  • 字段用于对用户请求数据的验证
  • 插件用于自动生成HTML;

【一】Field.clean(value)

  • 注意:这里说的是字段Field的clearn方法,不是表单Form的clean方法。
  • 虽然表单字段的Field类主要使用在Form类中,但也可以直接实例化它们来使用,以便更好地了解它们是如何工作的。
  • 每个Field的实例都有一个clean()方法,它接受一个参数,然后返回“清洁的”数据或者抛出一个django.forms.ValidationError异常:
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.']
  • 这个clean方法经常被我们用来在开发或测试过程中对某个字段的数据进行验证和测试。

【二】核心字段参数

【1】required

  • 设置表单项是否为必填项,如果未填写必填项,提交表单时将触发验证错误。

【2】initial

  • 为HTML页面中表单元素定义初始值。
  • 也就是input元素的value参数的值,如下所示:
from django import forms


class CommentForm(forms.Form):
    name = forms.CharField(initial='Your name')
    url = forms.URLField(initial='http://')
    comment = forms.CharField()


f = CommentForm(auto_id=False)
print(f)
# <tr><th>Name:</th><td><input type="text" name="name" value="Your name" required /></td></tr>
# <tr><th>Url:</th><td><input type="url" name="url" value="http://" required /></td></tr>
# <tr><th>Comment:</th><td><input type="text" name="comment" required /></td></tr>

  • 你可能会问为什么不在渲染表单的时候传递一个包含初始化值的字典给它,不是更方便?
  • 因为如果这么做,你将触发表单的验证过程,此时输出的HTML页面将包含验证中产生的错误,如下所示:
from django import forms


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


default_data = {'name': 'Your name', 'url': 'http://'}
f = CommentForm(default_data, auto_id=False)
print(f)
# <tr><th>Name:</th><td><input type="text" name="name" value="Your name" required /></td></tr>
# <tr><th>Url:</th><td><ul class="errorlist"><li>Enter a valid URL.</li></ul><input type="url" name="url" value="http://" required /></td></tr>
# <tr><th>Comment:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="comment" required /></td></tr>

  • 这就是为什么initial参数只用在未绑定的表单上。
  • 还要注意,如果提交表单时某个字段的值没有填写,initial的值不会作为“默认”的数据。initial值只用于原始表单的显示

【3】label

  • label参数用来给字段添加‘人类友好’的提示信息。
  • 如果没有设置这个参数,那么就用字段的首字母大写名字。
from django import forms


class CommentForm(forms.Form):
    name = forms.CharField(label='Your name')
    url = forms.URLField(label='Your website', required=False)
    comment = forms.CharField()


f = CommentForm(auto_id=False)
print(f)

# <tr><th>Your name:</th><td><input type="text" name="name" required /></td></tr>
# <tr><th>Your website:</th><td><input type="url" name="url" /></td></tr>
# <tr><th>Comment:</th><td><input type="text" name="comment" required /></td></tr>

【4】 label_suffix

  • Django默认为上面的label参数后面加个冒号后缀,如果想自定义,可以使用label_suffix参数。
  • 比如下面的例子用“?”代替了冒号:
from django import forms


class ContactForm(forms.Form):
    age = forms.IntegerField()
    nationality = forms.CharField()
    captcha_answer = forms.IntegerField(label='2 + 2', label_suffix=' =')


f = ContactForm(label_suffix='?')
print(f.as_p())

# <p><label for="id_age">Age?</label> <input id="id_age" name="age" type="number" required /></p>
# <p><label for="id_nationality">Nationality?</label> <input id="id_nationality" name="nationality" type="text" required /></p>
# <p><label for="id_captcha_answer">2 + 2 =</label> <input id="id_captcha_answer" name="captcha_answer" type="number" required /></p>

【5】widget

  • 最重要的参数之一,指定渲染Widget时使用的widget类,也就是这个form字段在HTML页面中是显示为文本输入框?密码输入框?单选按钮?多选框?还是别的....

【6】help_text

  • 该参数用于设置字段的辅助描述文本。
from django import forms


class HelpTextContactForm(forms.Form):
    subject = forms.CharField(max_length=100, help_text='100 characters max.')
    message = forms.CharField()
    sender = forms.EmailField(help_text='A valid email address, please.')
    cc_myself = forms.BooleanField(required=False)


f = HelpTextContactForm(auto_id=False)
print(f.as_table())
# <tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" required /><br /><span class="helptext">100 characters max.</span></td></tr>
# <tr><th>Message:</th><td><input type="text" name="message" required /></td></tr>
# <tr><th>Sender:</th><td><input type="email" name="sender" required /><br />A valid email address, please.</td></tr>
# <tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself" /></td></tr>
print(f.as_ul())
# <li>Subject: <input type="text" name="subject" maxlength="100" required /> <span class="helptext">100 characters max.</span></li>
# <li>Message: <input type="text" name="message" required /></li>
# <li>Sender: <input type="email" name="sender" required /> A valid email address, please.</li>
# <li>Cc myself: <input type="checkbox" name="cc_myself" /></li>
print(f.as_p())
# <p>Subject: <input type="text" name="subject" maxlength="100" required /> <span class="helptext">100 characters max.</span></p>
# <p>Message: <input type="text" name="message" required /></p>
# <p>Sender: <input type="email" name="sender" required /> A valid email address, please.</p>
# <p>Cc myself: <input type="checkbox" name="cc_myself" /></p>

【7】error_messages

  • 该参数允许你覆盖字段引发异常时的默认信息。
  • 传递的是一个字典,其键为你想覆盖的错误信息。
  • 例如,下面是默认的错误信息:
from django import forms

generic = forms.CharField()
generic.clean('')

# Traceback (most recent call last):
#   ...
# ValidationError: ['This field is required.']
  • 而下面是自定义的错误信息:
from django import forms

name = forms.CharField(error_messages={'required': 'Please enter your name'})
name.clean('')
# Traceback (most recent call last):
#   ...
# ValidationError: ['Please enter your name']
  • 可以指定多种类型的键,不仅仅针对‘requeired’错误,参考下面的内容。

【8】validators

  • 指定一个列表,其中包含了为字段进行验证的函数。

  • 也就是说,如果你自定义了验证方法,不用Django内置的验证功能,那么要通过这个参数,将字段和自定义的验证方法链接起来。

  • 参考前面的章节,学习如何编写验证器。

【9】localize

  • localize参数帮助实现表单数据输入的本地化。

【10】disabled

  • 设置有该属性的字段在前端页面中将显示为不可编辑状态。
  • 该参数接收布尔值,当设置为True时,使用HTML的disabled属性禁用表单域,以使用户无法编辑该字段。
  • 即使非法篡改了前端页面的属性,向服务器提交了该字段的值,也将依然被忽略。

【11】has_changed()方法

  • 和Form类似,每个Field也有一个has_changed()方法(注意这不是参数,是方法),用于判断字段的值是否发生了改变。

【12】password输入框

class LoginForm(forms.Form):
    ...
    pwd = forms.CharField(
        min_length=6,
        label="密码",
        widget=forms.widgets.PasswordInput(attrs={'class': 'c1'}, render_value=True)
    )

【13】radioSelect选择框

  • 单radio值为字符串
class LoginForm(forms.Form):
    username = forms.CharField(
        min_length=8,
        label="用户名",
        initial="张三",
        error_messages={
            "required": "不能为空",
            "invalid": "格式错误",
            "min_length": "用户名最短8位"
        }
    )
    pwd = forms.CharField(min_length=6, label="密码")
    gender = forms.fields.ChoiceField(
        choices=((1, "男"), (2, "女"), (3, "保密")),
        label="性别",
        initial=3,
        widget=forms.widgets.RadioSelect()
    )

【14】Select单选框

class LoginForm(forms.Form):
    ...
    hobby = forms.ChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=3,
        widget=forms.widgets.Select()
    )

【15】Select多选框

class LoginForm(forms.Form):
    ...
    hobby = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"), ),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.SelectMultiple()
    )

【16】checkbox单选框

class LoginForm(forms.Form):
    ...
    keep = forms.ChoiceField(
        label="是否记住密码",
        initial="checked",
        widget=forms.widgets.CheckboxInput()
    )

【17】checkbox多选框

class LoginForm(forms.Form):
    ...
    hobby = forms.MultipleChoiceField(
        choices=((1, "篮球"), (2, "足球"), (3, "双色球"),),
        label="爱好",
        initial=[1, 3],
        widget=forms.widgets.CheckboxSelectMultiple()
    )

【三】choice字段注意事项

  • 在使用选择标签时
    • 需要注意choices的选项可以配置从数据库中获取
  • 但是由于是静态字段
    • 获取的值无法实时更新
    • 需要重写构造方法从而实现choice实时更新。

【1】方式一

from django.forms import Form
from django.forms import widgets
from django.forms import fields

 
class MyForm(Form):
 
    user = fields.ChoiceField(
        # choices=((1, '上海'), (2, '北京'),),
        initial=2,
        widget=widgets.Select
    )
 
    def __init__(self, *args, **kwargs):
        super(MyForm,self).__init__(*args, **kwargs)
        # self.fields['user'].choices = ((1, '上海'), (2, '北京'),)
        # 或
        self.fields['user'].choices = models.Classes.objects.all().values_list('id','caption')

【2】方式二

from django import forms
from django.forms import fields
from django.forms import models as form_model

 
class FInfo(forms.Form):
    authors = form_model.ModelMultipleChoiceField(queryset=models.NNewType.objects.all())  # 多选
    # authors = form_model.ModelChoiceField(queryset=models.NNewType.objects.all())  # 单选

【四】自定义字段校验

【1】RegexValidator验证器

from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.validators import RegexValidator
 
class MyForm(Form):
    user = fields.CharField(
        validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
    )

【2】自定义验证函数

import re
from django.forms import Form
from django.forms import widgets
from django.forms import fields
from django.core.exceptions import ValidationError
 
 
# 自定义验证规则
def mobile_validate(value):
    mobile_re = re.compile(r'^(13[0-9]|15[012356789]|17[678]|18[0-9]|14[57])[0-9]{8}$')
    if not mobile_re.match(value):
        raise ValidationError('手机号码格式错误')
 
 
class PublishForm(Form):
 
 
    title = fields.CharField(max_length=20,
                            min_length=5,
                            error_messages={'required': '标题不能为空',
                                            'min_length': '标题最少为5个字符',
                                            'max_length': '标题最多为20个字符'},
                            widget=widgets.TextInput(attrs={'class': "form-control",
                                                          'placeholder': '标题5-20个字符'}))
 
 
    # 使用自定义验证规则
    phone = fields.CharField(validators=[mobile_validate, ],
                            error_messages={'required': '手机不能为空'},
                            widget=widgets.TextInput(attrs={'class': "form-control",
                                                          'placeholder': u'手机号码'}))
 
    email = fields.EmailField(required=False,
                            error_messages={'required': u'邮箱不能为空','invalid': u'邮箱格式错误'},
                            widget=widgets.TextInput(attrs={'class': "form-control", 'placeholder': u'邮箱'}))

【五】Django中的form所有内置字段

【1】总览

Field
    required=True,               是否允许为空
    widget=None,                 HTML插件
    label=None,                  用于生成Label标签或显示内容
    initial=None,                初始值
    help_text='',                帮助信息(在标签旁边显示)
    error_messages=None,         错误信息 {'required': '不能为空', 'invalid': '格式错误'}
    validators=[],               自定义验证规则
    localize=False,              是否支持本地化
    disabled=False,              是否可以编辑
    label_suffix=None            Label内容后缀
 
 
CharField(Field)
    max_length=None,             最大长度
    min_length=None,             最小长度
    strip=True                   是否移除用户输入空白
 
IntegerField(Field)
    max_value=None,              最大值
    min_value=None,              最小值
 
FloatField(IntegerField)
    ...
 
DecimalField(IntegerField)
    max_value=None,              最大值
    min_value=None,              最小值
    max_digits=None,             总长度
    decimal_places=None,         小数位长度
 
BaseTemporalField(Field)
    input_formats=None          时间格式化   
 
DateField(BaseTemporalField)    格式:2015-09-01
TimeField(BaseTemporalField)    格式:11:12
DateTimeField(BaseTemporalField)格式:2015-09-01 11:12
 
DurationField(Field)            时间间隔:%d %H:%M:%S.%f
    ...
 
RegexField(CharField)
    regex,                      自定制正则表达式
    max_length=None,            最大长度
    min_length=None,            最小长度
    error_message=None,         忽略,错误信息使用 error_messages={'invalid': '...'}
 
EmailField(CharField)      
    ...
 
FileField(Field)
    allow_empty_file=False     是否允许空文件
 
ImageField(FileField)      
    ...
    注:需要PIL模块,pip3 install Pillow
    以上两个字典使用时,需要注意两点:
        - form表单中 enctype="multipart/form-data"
        - view函数中 obj = MyForm(request.POST, request.FILES)
 
URLField(Field)
    ...
 
 
BooleanField(Field)  
    ...
 
NullBooleanField(BooleanField)
    ...
 
ChoiceField(Field)
    ...
    choices=(),                选项,如:choices = ((0,'上海'),(1,'北京'),)
    required=True,             是否必填
    widget=None,               插件,默认select插件
    label=None,                Label内容
    initial=None,              初始值
    help_text='',              帮助提示
 
 
ModelChoiceField(ChoiceField)
    ...                        django.forms.models.ModelChoiceField
    queryset,                  # 查询数据库中的数据
    empty_label="---------",   # 默认空显示内容
    to_field_name=None,        # HTML中value的值对应的字段
    limit_choices_to=None      # ModelForm中对queryset二次筛选
     
ModelMultipleChoiceField(ModelChoiceField)
    ...                        django.forms.models.ModelMultipleChoiceField
 
 
     
TypedChoiceField(ChoiceField)
    coerce = lambda val: val   对选中的值进行一次转换
    empty_value= ''            空值的默认值
 
MultipleChoiceField(ChoiceField)
    ...
 
TypedMultipleChoiceField(MultipleChoiceField)
    coerce = lambda val: val   对选中的每一个值进行一次转换
    empty_value= ''            空值的默认值
 
ComboField(Field)
    fields=()                  使用多个验证,如下:即验证最大长度20,又验证邮箱格式
                               fields.ComboField(fields=[fields.CharField(max_length=20), fields.EmailField(),])
 
MultiValueField(Field)
    PS: 抽象类,子类中可以实现聚合多个字典去匹配一个值,要配合MultiWidget使用
 
SplitDateTimeField(MultiValueField)
    input_date_formats=None,   格式列表:['%Y--%m--%d', '%m%d/%Y', '%m/%d/%y']
    input_time_formats=None    格式列表:['%H:%M:%S', '%H:%M:%S.%f', '%H:%M']
 
FilePathField(ChoiceField)     文件选项,目录下文件显示在页面中
    path,                      文件夹路径
    match=None,                正则匹配
    recursive=False,           递归下面的文件夹
    allow_files=True,          允许文件
    allow_folders=False,       允许文件夹
    required=True,
    widget=None,
    label=None,
    initial=None,
    help_text=''
 
GenericIPAddressField
    protocol='both',           both,ipv4,ipv6支持的IP格式
    unpack_ipv4=False          解析ipv4地址,如果是::ffff:192.0.2.1时候,可解析为192.0.2.1, PS:protocol必须为both才能启用
 
SlugField(CharField)           数字,字母,下划线,减号(连字符)
    ...
 
UUIDField(CharField)           uuid类型

【2】概述

(1)BooleanField

  • 默认的Widget:CheckboxInput
  • 空值:False
  • 规范化为:Python的True或者False
  • 可用的错误信息键:required

(2)CharField

  • 默认的Widget:TextInput
  • 空值:与empty_value给出的任何值。
  • 规范化为:一个Unicode 对象。
  • 验证max_lengthmin_length,如果设置了这两个参数。 否则,所有的输入都是合法的。
  • 可用的错误信息键:min_length, max_length, required

有四个可选参数:

  • max_length,min_length:设置字符串的最大和最小长度。
  • strip:如果True(默认),去除输入的前导和尾随空格。
  • empty_value:用来表示“空”的值。 默认为空字符串。

(3)ChoiceField

  • 默认的Widget:Select
  • 空值:''(一个空字符串)
  • 规范化为:一个Unicode 对象。
  • 验证给定的值是否在选项列表中。
  • 可用的错误信息键:required, invalid_choice

参数choices:

用来作为该字段选项的一个二元组组成的可迭代对象(例如,列表或元组)或者一个可调用对象。

格式与用于和ORM模型字段的choices参数相同。

(4)TypedChoiceField

像ChoiceField一样,只是还有两个额外的参数:coerce和empty_value。

  • 默认的Widget:Select
  • 空值:empty_value参数设置的值。
  • 规范化为:coerce参数类型的值。
  • 验证给定的值在选项列表中存在并且可以被强制转换。
  • 可用的错误信息的键:required, invalid_choice

(5)DateField

  • 默认的Widget:DateInput
  • 空值:None
  • 规范化为:datetime.date对象。
  • 验证给出的值是一个datetime.date、datetime.datetime 或指定日期格式的字符串。
  • 错误信息的键:required, invalid

接收一个可选的参数:input_formats。

一个格式的列表,用于转换字符串为datetime.date对象。

如果没有提供input_formats,默认的输入格式为:

['%Y-%m-%d',      # '2006-10-25'
 '%m/%d/%Y',      # '10/25/2006'
 '%m/%d/%y']      # '10/25/06'

另外,如果你在设置中指定USE_L10N=False,以下的格式也将包含在默认的输入格式中:

['%b %d %Y',      # 'Oct 25 2006'
 '%b %d, %Y',     # 'Oct 25, 2006'
 '%d %b %Y',      # '25 Oct 2006'
 '%d %b, %Y',     # '25 Oct, 2006'
 '%B %d %Y',      # 'October 25 2006'
 '%B %d, %Y',     # 'October 25, 2006'
 '%d %B %Y',      # '25 October 2006'
 '%d %B, %Y']     # '25 October, 2006'

(6)DateTimeField

  • 默认的Widget:DateTimeInput
  • 空值:None
  • 规范化为:Python的datetime.datetime对象。
  • 验证给出的值是一个datetime.datetime、datetime.date或指定日期格式的字符串。
  • 错误信息的键:required, invalid

接收一个可选的参数:input_formats

如果没有提供input_formats,默认的输入格式为:

['%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'

(7)DecimalField

  • 默认的Widget:当Field.localize是False时为NumberInput,否则为TextInput。
  • 空值:None
  • 规范化为: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)DurationField

  • 默认的Widget:TextInput
  • 空值:None
  • 规范化为:Python timedelta。
  • 验证给出的值是一个字符串,而且可以转换为timedelta对象。
  • 错误信息的键:required, invalid.

(9)EmailField

  • 默认的Widget:EmailInput
  • 空值:''(一个空字符串)
  • 规范化为:Unicode 对象。
  • 使用正则表达式验证给出的值是一个合法的邮件地址。
  • 错误信息的键:required, invalid

两个可选的参数用于验证,max_length 和min_length。

(10)FileField

  • 默认的Widget:ClearableFileInput
  • 空值:None
  • 规范化为:一个UploadedFile对象,它封装文件内容和文件名到一个对象内。
  • 验证非空的文件数据已经绑定到表单。
  • 错误信息的键:missing, invalid, required, empty, max_length

具有两个可选的参数用于验证:max_length 和 allow_empty_file。

(11)FilePathField

  • 默认的Widget:Select
  • 空值:None
  • 规范化为:Unicode 对象。
  • 验证选择的选项在选项列表中存在。
  • 错误信息的键:required, invalid_choice

这个字段允许从一个特定的目录选择文件。 它有五个额外的参数,其中的path是必须的:

path:要列出的目录的绝对路径。 这个目录必须存在。

recursive:如果为False(默认值),只用直接位于path下的文件或目录作为选项。如果为True,将递归访问这个目录,其内所有的子目录和文件都将作为选项。

match:正则表达模式;只有具有与此表达式匹配的文件名称才被允许作为选项。

allow_files:可选。默认为True。表示是否应该包含指定位置的文件。它和allow_folders必须有一个为True。

allow_folders可选。默认为False。表示是否应该包含指定位置的目录。

(12)FloatField

  • 默认的Widget:当Field.localize是False时为NumberInput,否则为TextInput。
  • 空值:None
  • 规范化为:Float 对象。
  • 验证给定的值是一个浮点数。
  • 错误信息的键:max_value, invalid, required, min_value

接收两个可选的参数用于验证,max_value和min_value,控制允许的值的范围。

(13)ImageField

  • 默认的Widget:ClearableFileInput
  • 空值:None
  • 规范化为:一个UploadedFile 象,它封装文件内容和文件名为一个单独的对象。
  • 验证文件数据已绑定到表单,并且该文件是Pillow可以解析的图像格式。
  • 错误信息的键:missing, invalid, required, empty, invalid_image

使用ImageField需要安装Pillow(pip install pillow)。如果在上传图片时遇到图像损坏错误,通常意味着使用了Pillow不支持的格式。

>>> from PIL import Image
>>> from django import forms
>>> from django.core.files.uploadedfile import SimpleUploadedFile
>>> class ImageForm(forms.Form):
...     img = forms.ImageField()
>>> file_data = {'img': SimpleUploadedFile('test.png', <file data>)}
>>> form = ImageForm({}, file_data)
# Pillow closes the underlying file descriptor.
>>> form.is_valid()
True
>>> image_field = form.cleaned_data['img']
>>> image_field.image
<PIL.PngImagePlugin.PngImageFile image mode=RGBA size=191x287 at 0x7F5985045C18>
>>> image_field.image.width
191
>>> image_field.image.height
287
>>> image_field.image.format
'PNG'
>>> image_field.image.getdata()
# Raises AttributeError: 'NoneType' object has no attribute 'seek'.
>>> image = Image.open(image_field)
>>> image.getdata()
<ImagingCore object at 0x7f5984f874b0>

(14)IntegerField

  • 默认的Widget:当Field.localize是False时为NumberInput,否则为TextInput。
  • 空值:None
  • 规范化为:Python 整数或长整数。
  • 验证给定值是一个整数。 允许前导和尾随空格,类似Python的int()函数。
  • 错误信息的键:max_value, invalid, required, min_value

两个可选参数:max_value和min_value,控制允许的值的范围。

(15)JSONField

Django3.1新增。

接收JSON编码的字段。

  • 默认的Widget:Textarea
  • 空值:None
  • 规范化为:一个JSON对象。
  • 验证给定值是否合法的JSON。
  • 错误信息的键:required, invalid
  • 可接受两个参数:encoder和decoder,编码器和解码器

(16)GenericIPAddressField

包含IPv4或IPv6地址的字段。

  • 默认的Widget:TextInput
  • 空值:''(一个空字符串)
  • 规范化为:一个Unicode对象。
  • 验证给定值是有效的IP地址。
  • 错误信息的键:required, invalid

有两个可选参数:protocol和unpack_ipv4

(17)MultipleChoiceField

  • 默认的Widget:SelectMultiple
  • 空值:[](一个空列表)
  • 规范化为:一个Unicode 对象列表。
  • 验证给定值列表中的每个值都存在于选择列表中。
  • 错误信息的键:invalid_list, invalid_choice, required

(18)TypedMultipleChoiceField

类似MultipleChoiceField,除了需要两个额外的参数,coerce和empty_value。

  • 默认的Widget:SelectMultiple
  • 空值:empty_value
  • 规范化为:coerce参数提供的类型值列表。
  • 验证给定值存在于选项列表中并且可以强制。
  • 错误信息的键:required, invalid_choice

(19)NullBooleanField

  • 默认的Widget:NullBooleanSelect
  • 空值:None
  • 规范化为:Python None, False 或True 值。
  • 不验证任何内容(即,它从不引发ValidationError)。

(20)RegexField

  • 默认的Widget:TextInput
  • 空值:''(一个空字符串)
  • 规范化为:一个Unicode 对象。
  • 验证给定值与某个正则表达式匹配。
  • 错误信息的键:required, invalid

需要一个必需的参数:regex,需要匹配的正则表达式。

还可以接收max_length,min_length和strip参数,类似CharField。

(21)SlugField

  • 默认的Widget:TextInput
  • 空值:''(一个空字符串)
  • 规范化为:一个Unicode 对象。
  • 验证给定的字符串只包括字母、数字、下划线及连字符。
  • 错误信息的键:required, invalid

此字段用于在表单中表示模型的SlugField。

(22)TimeField

  • 默认的Widget:TextInput
  • 空值:None
  • 规范化为:一个Python 的datetime.time 对象。
  • 验证给定值是datetime.time或以特定时间格式格式化的字符串。
  • 错误信息的键:required, invalid

接收一个可选的参数:input_formats,用于尝试将字符串转换为有效的datetime.time对象的格式列表。

如果没有提供input_formats,默认的输入格式为:

'%H:%M:%S',     # '14:30:59'
'%H:%M',        # '14:30'

(23)URLField

  • 默认的Widget:URLInput
  • 空值:''(一个空字符串)
  • 规范化为:一个Unicode 对象。
  • 验证给定值是个有效的URL。
  • 错误信息的键:required, invalid

可选参数:max_length和min_length

(24)UUIDField

  • 默认的Widget:TextInput
  • 空值:''(一个空字符串)
  • 规范化为:UUID对象。
  • 错误信息的键:required, invalid

(25) ComboField

  • 默认的Widget:TextInput
  • 空值:''(一个空字符串)
  • 规范化为:Unicode 对象。
  • 根据指定为ComboField的参数的每个字段验证给定值。
  • 错误信息的键:required, invalid

接收一个额外的必选参数:fields,用于验证字段值的字段列表(按提供它们的顺序)。

>>> from django.forms import ComboField
>>> f = ComboField(fields=[CharField(max_length=20), EmailField()])
>>> f.clean('test@example.com')
'test@example.com'
>>> f.clean('longemailaddress@example.com')
Traceback (most recent call last):
...
ValidationError: ['Ensure this value has at most 20 characters (it has 28).']

(26)MultiValueField

  • 默认的Widget:TextInput
  • 空值:''(一个空字符串)
  • 规范化为:子类的compress方法返回的类型。
  • 根据指定为MultiValueField的参数的每个字段验证给定值。
  • 错误信息的键:incomplete, invalid, required

(27)SplitDateTimeField

  • 默认的Widget:SplitDateTimeWidget
  • 空值:None
  • 规范化为:Python datetime.datetime 对象。
  • 验证给定的值是datetime.datetime或以特定日期时间格式格式化的字符串。
  • 错误信息的键:invalid_date, invalid, required, invalid_time

【3】创建自定义字段

  • 如果内置的Field真的不能满足你的需求,还可以自定义Field。
  • 只需要创建一个django.forms.Field的子类,并实现clean()和__init__()构造方法。__init__()构造方法需要接收前面提过的那些核心参数,比如widget、required,、label、help_text、initial。
  • 还可以通过覆盖get_bound_field()方法来自定义访问字段的方式。

【补充】forms组件参数总结

【1】基本参数

【1】autocomplete

  • 设置是否启用自动填充功能,可以使用以下值:

  • on:浏览器自动填充表单项。

  • off:禁用浏览器自动填充。

【2】disabled

  • 设置表单项是否禁用,禁用后用户无法编辑或选择该项的值。

【3】readonly

  • 设置表单项是否只读,只读的表单项可以显示但不允许用户修改。

【4】maxmin

  • 用于限制数字或日期类型的输入值的最大和最小值。

【5】***maxlengthminlength

  • 设置输入值的最大长度和最小长度,超过或低于长度限制时将触发验证错误。

【6】pattern

  • 使用正则表达式指定输入值的格式验证规则。

【7】required

  • 设置表单项是否为必填项,如果未填写必填项,提交表单时将触发验证错误。

【8】step

  • 用于数字类型的输入值,指定允许的增量或减量范围。

【9】aria-describedby

  • 指定与表单项关联的描述性文本的id,辅助技术可以使用此信息提供更好的可访问性。

【10】aria-invalid

  • 设置是否将表单项标记为无效,如果表单项的值不符合验证规则,可以将其设置为"true"。

【2】参数详解

(1)***widget:添加标签属性

  • 指定字段的控件显示方式。
  • 可以使用各种预定义的小部件(widgets)或自定义的小部件类。
  • 例如,可以使用 forms.TextInput 将字段以文本框的形式显示出来:
from django import forms

class MyForm(forms.Form):
    username = forms.CharField(
        max_length=8,
        min_length=3,
        label="用户名",
        widget=forms.TextInput(attrs={"class": "form-control"})
    )
  • 在Django的表单中
    • widget参数用于设置表单字段的展示方式或使用自定义的HTML元素来呈现字段。
  • widget参数
    • 可以接受一个Django提供的内置的小部件类(widget class)
    • 也可以使用自定义的小部件类。
  • 以下是几个常用的小部件类及其作用:
  1. forms.TextInput:默认的文本输入框小部件。
  2. forms.Textarea:多行文本输入框小部件。
  3. forms.CheckboxInput:复选框小部件。
  4. forms.Select:下拉选择框小部件。
  5. forms.RadioSelect:单选按钮小部件。
  6. forms.FileInput:文件上传小部件。
  7. forms.HiddenInput:隐藏输入框小部件。
  • 下面是一个示例代码片段
    • 演示如何使用widget参数定义一个表单字段的小部件:
from django import forms

class MyForm(forms.Form):
    username = forms.CharField(
        max_length=100,
        widget=forms.TextInput(attrs={'class': 'my-custom-class'})
    )
    password = forms.CharField(
        max_length=100,
        widget=forms.PasswordInput()
    )
  • 上述代码中
    • username 字段使用自定义的CSS类样式,并将其应用到一个文本输入框小部件中。
    • password 字段则使用了密码输入框小部件。
  • 需要注意的是
    • 可以通过attrs参数传递其他的HTML属性给小部件。
    • 例如,在上面的示例中,我们为username字段定义了class属性。
  • 另外
    • 如果想要使用自定义的小部件类
    • 可以定义一个继承自Django小部件类的类,并将其传递给widget参数。例如:
from django import forms

class MyCustomWidget(forms.widgets.TextInput):
    # 自定义的小部件类

class MyForm(forms.Form):
    my_field = forms.CharField(
        widget=MyCustomWidget()
    )
  • 上述代码中
    • 我们创建了一个名为MyCustomWidget的自定义小部件类,
    • 并将其用于my_field字段。
  • 通过使用widget参数
    • 我们可以对Django表单字段的展示方式进行灵活的定制
    • 以满足具体项目的需求。

(2)***required:是否为必填字段

  • 设置字段是否为必填项,默认为 True
  • 如果设置为 False,则允许用户提交空值。例如:
class MyForm(forms.Form):
    username = forms.CharField(
        max_length=8,
        min_length=3,
        label="用户名",
        required=False
    )

(3)***label:自定义标签文本

  • 指定字段的标签显示文本。
  • 可以使用该参数自定义字段在表单中的标签文本。例如:
class MyForm(forms.Form):
    username = forms.CharField(
        max_length=8,
        min_length=3,
        label="Your Username"
    )

(4)***error_messages:标签不合法的提示信息

  • 用于自定义错误消息。
  • 可以通过该参数自定义字段验证失败时显示的错误消息。例如:
class MyForm(forms.Form):
    username = forms.CharField(
        max_length=8,
        min_length=3,
        label="用户名",
        error_messages={
            "max_length": "用户名最多为8个字符",
            "min_length": "用户名至少为3个字符",
            "required": "请填写用户名"
        }
    )

(5)help_text:描述提醒信息

  • 为字段提供帮助文本。
  • 可以使用该参数为字段添加描述性的帮助文本,以向用户解释该字段的用途或提供输入建议。例如:
class MyForm(forms.Form):
    username = forms.CharField(
        max_length=8,
        min_length=3,
        label="用户名",
        help_text="请输入3-8个字符的用户名"
    )

(6)***validators:正则表达式

  • 用于自定义字段验证器。
  • 可以使用该参数添加额外的验证函数来对字段进行更复杂的验证。例如:
from django.core.validators import RegexValidator

class MyForm(forms.Form):
    username = forms.CharField(
        max_length=8,
        min_length=3,
        label="用户名",
        validators=[
            RegexValidator(
                regex=r"^[a-zA-Z]+$",
                message="只允许字母字符"
            )
        ]
    )

(7)***initial:默认值

  • 可以通过 initial 参数为表单字段设置默认值。
  • 该参数指定了在表单加载时显示的初始值。以下是示例代码:
from django import forms

class MyForm(forms.Form):
    username = forms.CharField(
        max_length=8,
        min_length=3,
        label="用户名",
        initial="JohnDoe"
    )
  • 在上述示例中
    • username 字段将显示一个文本框
    • 并且默认值为 "JohnDoe"。
  • 另外
    • 如果要为多个字段设置默认值
    • 可以通过使用 initial 字典来一次性设置多个字段的初始值。例如:
from django import forms

class MyForm(forms.Form):
    username = forms.CharField(
        max_length=8,
        min_length=3,
        label="用户名"
    )
    email = forms.EmailField(
        label="邮箱"
    )

    initial = {
        'username': 'JohnDoe',
        'email': 'johndoe@example.com'
    }
  • 可以在实例化表单对象时传递 initial 字典来设置这两个字段的默认值:
form = MyForm(initial={
    'username': 'JohnSmith',
    'email': 'johnsmith@example.com'
})
  • 当表单加载时
    • username 字段将显示为 "JohnSmith"
    • email 字段将显示为 "johnsmith@example.com"。
  • 这样
    • 通过使用 initial 参数
    • 可以方便地为表单字段设置默认值,提供更好的用户体验。

【3】其他字段渲染

(1)radioSelect(单选)

  • 您可以在表单类中使用forms.RadioSelect字段来渲染radioSelect字段。下面是一个案例演示:
from django import forms

class GenderForm(forms.Form):
    gender_choices = [
        ('male', 'Male'),
        ('female', 'Female'),
    ]
    gender = forms.ChoiceField(choices=gender_choices, widget=forms.RadioSelect)
  • 在这个案例中,我们定义了一个名为GenderForm的表单类,其中包含了一个gender字段用于选择性别。
  • 通过设置widget=forms.RadioSelect,我们将该字段渲染为单选按钮。

(2)单选Select

  • 您可以使用forms.Select字段来呈现下拉菜单形式的单选选项。以下是一个案例演示:
from django import forms

class CityForm(forms.Form):
    city_choices = [
        ('1', 'New York'),
        ('2', 'London'),
        ('3', 'Tokyo'),
    ]
    city = forms.ChoiceField(choices=city_choices, widget=forms.Select)
  • 在这个案例中,我们定义了一个名为CityForm的表单类,其中包含了一个city字段用于选择城市。通过设置widget=forms.Select,我们将该字段渲染为下拉菜单。

(3)多选Select

  • 使用forms.SelectMultiple字段可以渲染多选Select组件。以下是一个案例演示:
from django import forms

class InterestsForm(forms.Form):
    interest_choices = [
        ('coding', 'Coding'),
        ('gaming', 'Gaming'),
        ('reading', 'Reading'),
    ]
    interests = forms.MultipleChoiceField(choices=interest_choices, widget=forms.SelectMultiple)
  • 在这个案例中,我们定义了一个名为InterestsForm的表单类
  • 其中包含了一个interests字段用于选择兴趣。
  • 通过设置widget=forms.SelectMultiple,我们将该字段渲染为支持多选的下拉菜单。

(4)单选checkbox

  • 要渲染单选checkbox字段,您可以使用forms.CheckboxInput字段。
  • 以下是一个案例演示:
from django import forms

class AgreeForm(forms.Form):
    agree = forms.BooleanField(widget=forms.CheckboxInput)
  • 在这个案例中,我们定义了一个名为AgreeForm的表单类
  • 其中包含了一个agree字段用于接受条款。
  • 通过设置widget=forms.CheckboxInput,我们将该字段渲染为单选复选框。

(5)多选checkbox

  • 要渲染多选checkbox字段
  • 可以使用forms.CheckboxSelectMultiple字段。
  • 以下是一个案例演示:
from django import forms

class ColorsForm(forms.Form):
    color_choices = [
        ('red', 'Red'),
        ('green', 'Green'),
        ('blue', 'Blue'),
    ]
    colors = forms.MultipleChoiceField(choices=color_choices, widget=forms.CheckboxSelectMultiple)
  • 在这个案例中,我们定义了一个名为ColorsForm的表单类,其中包含了一个colors字段用于选择颜色。
  • 通过设置widget=forms.CheckboxSelectMultiple,我们将该字段渲染为多个复选框供用户选择。

posted @ 2024-03-18 23:18  Chimengmeng  阅读(136)  评论(0编辑  收藏  举报