表单字段

class Field(**kwargs)

当你创建一个 Form 类时,最重要的部分是定义表单的字段。每个字段都有自定义的验证逻辑,以及其他一些钩子。

Field.clean(value)

虽然你主要会在 Form 类中使用 Field 类,但你也可以实例化它们并直接使用它们来更好地了解它们的工作原理。每个 Field 实例都有一个 clean() 方法,它接受一个参数,要么引发一个 django.core.exceptions.ValidationError 异常,要么返回清理后的值:

  1. >>> from django import forms
  2. >>> f = forms.EmailField()
  3. >>> f.clean("foo@example.com")
  4. 'foo@example.com'
  5. >>> f.clean("invalid email address")
  6. Traceback (most recent call last):
  7. ...
  8. ValidationError: ['Enter a valid email address.']

核心字段参数

每个 Field 类的构造函数至少需要这些参数。有些 Field 类需要额外的、特定的字段参数,但以下参数应 始终 接受:

required

Field.required

默认情况下,每个 Field 类都假定该值是必需的,因此如果传递一个空值 — 无论是 None 还是空字符串("")— 那么 clean() 将引发一个 ValidationError 异常:

  1. >>> from django import forms
  2. >>> f = forms.CharField()
  3. >>> f.clean("foo")
  4. 'foo'
  5. >>> f.clean("")
  6. Traceback (most recent call last):
  7. ...
  8. ValidationError: ['This field is required.']
  9. >>> f.clean(None)
  10. Traceback (most recent call last):
  11. ...
  12. ValidationError: ['This field is required.']
  13. >>> f.clean(" ")
  14. ' '
  15. >>> f.clean(0)
  16. '0'
  17. >>> f.clean(True)
  18. 'True'
  19. >>> f.clean(False)
  20. 'False'

要指定字段为 必需的,请将 required=False 传递给 Field 构造函数:

  1. >>> f = forms.CharField(required=False)
  2. >>> f.clean("foo")
  3. 'foo'
  4. >>> f.clean("")
  5. ''
  6. >>> f.clean(None)
  7. ''
  8. >>> f.clean(0)
  9. '0'
  10. >>> f.clean(True)
  11. 'True'
  12. >>> f.clean(False)
  13. 'False'

如果一个 Fieldrequired=False,而你给 clean() 传递一个空值,那么 clean() 将返回一个 规范化 的空值,而不是引发 ValidationError。对于 CharField,将返回 empty_value,默认为一个空字符串。对于其他 Field 类,它可能是 None。(这因字段而异。)

必填表单字段的部件有 required HTML 属性。将 Form.use_required_attribute 属性设置为 False 就可以禁用。由于在添加和删除表单集时,浏览器的验证可能不正确,所以表单集的表单中不包含 required 属性。

label

Field.label

label 参数让你指定该字段的“人类友好”标签。当 FieldForm 中显示时,会用到这个标签。

如上文“将表格输出为 HTML”中所解释的,Field 的默认标签是由字段名通过将所有下划线转换为空格并将第一个字母大写而生成的。如果默认行为不能产生一个适当的标签,请指定 label

以下是一个完整的示例 Form,它为其两个字段实现了 label。我们指定了 auto_id=False 以简化输出:

  1. >>> from django import forms
  2. >>> class CommentForm(forms.Form):
  3. ... name = forms.CharField(label="Your name")
  4. ... url = forms.URLField(label="Your website", required=False)
  5. ... comment = forms.CharField()
  6. ...
  7. >>> f = CommentForm(auto_id=False)
  8. >>> print(f)
  9. <tr><th>Your name:</th><td><input type="text" name="name" required></td></tr>
  10. <tr><th>Your website:</th><td><input type="url" name="url"></td></tr>
  11. <tr><th>Comment:</th><td><input type="text" name="comment" required></td></tr>

label_suffix

Field.label_suffix

label_suffix 参数允许你以每个字段为基础覆盖表单的 label_suffix

  1. >>> class ContactForm(forms.Form):
  2. ... age = forms.IntegerField()
  3. ... nationality = forms.CharField()
  4. ... captcha_answer = forms.IntegerField(label="2 + 2", label_suffix=" =")
  5. ...
  6. >>> f = ContactForm(label_suffix="?")
  7. >>> print(f.as_p())
  8. <p><label for="id_age">Age?</label> <input id="id_age" name="age" type="number" required></p>
  9. <p><label for="id_nationality">Nationality?</label> <input id="id_nationality" name="nationality" type="text" required></p>
  10. <p><label for="id_captcha_answer">2 + 2 =</label> <input id="id_captcha_answer" name="captcha_answer" type="number" required></p>

initial

Field.initial

initial 参数让你指定在未绑定的 Form 中渲染这个 Field 时要使用的初始值。

要指定动态初始数据,请参见 Form.initial 参数。

这个用例是当你想要显示一个 “空” 表单,其中一个字段被初始化为特定的值时。例如:

  1. >>> from django import forms
  2. >>> class CommentForm(forms.Form):
  3. ... name = forms.CharField(initial="Your name")
  4. ... url = forms.URLField(initial="http://")
  5. ... comment = forms.CharField()
  6. ...
  7. >>> f = CommentForm(auto_id=False)
  8. >>> print(f)
  9. <tr><th>Name:</th><td><input type="text" name="name" value="Your name" required></td></tr>
  10. <tr><th>Url:</th><td><input type="url" name="url" value="http://" required></td></tr>
  11. <tr><th>Comment:</th><td><input type="text" name="comment" required></td></tr>

你可能会想,为什么不在显示表单时直接传递初始值的字典作为数据呢?如果你这样做,你会触发验证,并且 HTML 输出将包含任何验证错误:

  1. >>> class CommentForm(forms.Form):
  2. ... name = forms.CharField()
  3. ... url = forms.URLField()
  4. ... comment = forms.CharField()
  5. ...
  6. >>> default_data = {"name": "Your name", "url": "http://"}
  7. >>> f = CommentForm(default_data, auto_id=False)
  8. >>> print(f)
  9. <tr><th>Name:</th><td><input type="text" name="name" value="Your name" required></td></tr>
  10. <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>
  11. <tr><th>Comment:</th><td><ul class="errorlist"><li>This field is required.</li></ul><input type="text" name="comment" required></td></tr>

这就是为什么 initial 值只在未绑定的表单中显示。对于绑定的表格,HTML 输出将使用绑定的数据。

还要注意,如果没有提供特定字段的值,initial 会用作验证的 “回退” 数据。initial 值仅用于初始表单显示:

  1. >>> class CommentForm(forms.Form):
  2. ... name = forms.CharField(initial="Your name")
  3. ... url = forms.URLField(initial="http://")
  4. ... comment = forms.CharField()
  5. ...
  6. >>> data = {"name": "", "url": "", "comment": "Foo"}
  7. >>> f = CommentForm(data)
  8. >>> f.is_valid()
  9. False
  10. # The form does *not* fall back to using the initial values.
  11. >>> f.errors
  12. {'url': ['This field is required.'], 'name': ['This field is required.']}

而不是一个常量,你也可以传递任何可调用的对象:

  1. >>> import datetime
  2. >>> class DateForm(forms.Form):
  3. ... day = forms.DateField(initial=datetime.date.today)
  4. ...
  5. >>> print(DateForm())
  6. <tr><th>Day:</th><td><input type="text" name="day" value="12/23/2008" required><td></tr>

只有在显示未绑定的表单时,而不是在定义表单时,才会对可调用对象表单执行。

widget

Field.widget

widget 参数让你指定一个 Widget 类,以便在渲染这个 Field 时使用。参见 部件 了解更多信息。

help_text

Field.help_text

help_text 参数让你为这个 Field 指定描述性文本。如果你提供了 help_text,当 Field 被一个方便的 Form 方法(例如 as_ul())渲染时,它将显示在 Field` 旁边。

就像模型字段的 help_text 一样,这个值在自动生成的表单中并没有被 HTML 封装。

以下是一个完整的示例 Form,它为其两个字段实现了 help_text。我们指定了 auto_id=False 以简化输出:

  1. >>> from django import forms
  2. >>> class HelpTextContactForm(forms.Form):
  3. ... subject = forms.CharField(max_length=100, help_text="100 characters max.")
  4. ... message = forms.CharField()
  5. ... sender = forms.EmailField(help_text="A valid email address, please.")
  6. ... cc_myself = forms.BooleanField(required=False)
  7. ...
  8. >>> f = HelpTextContactForm(auto_id=False)
  9. >>> print(f.as_table())
  10. <tr><th>Subject:</th><td><input type="text" name="subject" maxlength="100" required><br><span class="helptext">100 characters max.</span></td></tr>
  11. <tr><th>Message:</th><td><input type="text" name="message" required></td></tr>
  12. <tr><th>Sender:</th><td><input type="email" name="sender" required><br>A valid email address, please.</td></tr>
  13. <tr><th>Cc myself:</th><td><input type="checkbox" name="cc_myself"></td></tr>
  14. >>> print(f.as_ul())
  15. <li>Subject: <input type="text" name="subject" maxlength="100" required> <span class="helptext">100 characters max.</span></li>
  16. <li>Message: <input type="text" name="message" required></li>
  17. <li>Sender: <input type="email" name="sender" required> A valid email address, please.</li>
  18. <li>Cc myself: <input type="checkbox" name="cc_myself"></li>
  19. >>> print(f.as_p())
  20. <p>Subject: <input type="text" name="subject" maxlength="100" required> <span class="helptext">100 characters max.</span></p>
  21. <p>Message: <input type="text" name="message" required></p>
  22. <p>Sender: <input type="email" name="sender" required> A valid email address, please.</p>
  23. <p>Cc myself: <input type="checkbox" name="cc_myself"></p>

error_messages

Field.error_messages

error_messages 参数允许你覆盖字段将引发的默认消息。传递一个字典,其中的键与你想要覆盖的错误消息匹配。例如,这是默认的错误消息:

  1. >>> from django import forms
  2. >>> generic = forms.CharField()
  3. >>> generic.clean("")
  4. Traceback (most recent call last):
  5. ...
  6. ValidationError: ['This field is required.']

以下是一个自定义错误消息的示例:

  1. >>> name = forms.CharField(error_messages={"required": "Please enter your name"})
  2. >>> name.clean("")
  3. Traceback (most recent call last):
  4. ...
  5. ValidationError: ['Please enter your name']

在下面的 内置字段类 一节中,每个 Field 定义了它所使用的错误信息键。

validators

Field.validators

validators 参数让你为这个字段提供一个验证函数列表。

更多信息请参见 验证器文档

localize

Field.localize

localize 参数可以实现表单数据输入和渲染输出的本地化。

更多信息请参见 格式本地化 文档。

disabled

Field.disabled

disabled 布尔参数设置为 True 时,使用 disabled HTML 属性禁用表单字段,使其不能被用户编辑。即使用户篡改了提交给服务器的字段值,也会被忽略,而采用表单初始数据的值。

检查字段数据是否有变化

has_changed()

Field.has_changed()

has_changed() 方法用于确定字段值是否与初始值发生了变化。返回 TrueFalse

更多信息请参见 Form.has_changed() 文档。

内置 Field

当然,forms 库附带了一组 Field 类,代表了常见的验证需求。本节将对每个内置字段进行说明。

对于每个字段,我们描述了在你没有指定 widget 时使用的默认部件。我们还指定了当你提供一个空值时返回的值(参见上文 required 一节以了解其含义)。

BooleanField

class BooleanField(**kwargs)

  • 默认部件:CheckboxInput
  • 空值:False
  • 规范化为:Python 的 TrueFalse 值。
  • 如果字段有 required=True,则验证该值是否为 True (例如,复选框被选中)。
  • 错误信息键:required

备注

由于所有 Field 子类默认都有 required=True,这里的验证条件很重要。如果你想在你的表单中包含一个布尔值,这个布尔值可以是 TrueFalse (例如一个选中或未选中的复选框),你必须记得在创建 BooleanField 时传递 required=False

CharField

class CharField(**kwargs)

  • 默认部件:TextInput
  • 空值:不管你给 empty_value 的是什么。
  • 规范化为:一个字符串。
  • 如果提供了 max_lengthmin_length,则使用 MaxLengthValidatorMinLengthValidator。否则,所有输入都有效。
  • 错误信息键:requiredmax_lengthmin_length

具有以下可选的验证参数:

  • max_length

  • min_length

    如果提供了这些参数,这些参数确保字符串的长度最多或至少是给定的长度。

  • strip

    如果 True (默认),该值将被去掉前导和尾部的空白。

  • empty_value

    用来表示“空”的值。默认为空字符串。

ChoiceField

class ChoiceField(**kwargs)

  • 默认部件:Select
  • 空值:'' (空字符串)
  • 规范化为:一个字符串。
  • 验证给定值是否存在于选择列表中。
  • 错误信息键:requiredinvalid_choice

invalid_choice 错误信息可能包含 %(value)s,该信息将被替换为选定的选择。

需要一个额外的参数:

  • choices

    或者是一个 iterable 的二元元组作为这个字段的选择,或者是一个 enumeration 的选择,或者是一个返回这样一个迭代器的可调用对象。这个参数接受的格式与模型字段的 choices 参数相同。更多细节请参见 模型字段引用文档中的选择。如果这个参数是可调用的,那么除了在渲染过程中,每次初始化字段的表单时,它都会被执行。默认为空列表。

选择类型

这个字段将选择项标准化为字符串,所以如果选择项需要其他数据类型,比如整数或布尔值,请考虑使用 TypedChoiceField 代替。

DateField

class DateField(**kwargs)

  • 默认部件:DateInput
  • 空值:None
  • 规范化为:Python 的 datetime.date 对象。
  • 验证给定值是 datetime.datedatetime.datetime 或以特定日期格式化的字符串。
  • 错误信息键:requiredinvalid

需要一个可选的参数:

  • input_formats

    一个用于尝试将字符串转换为有效的 datetime.date 对象的格式迭代器。

如果没有提供 input_formats 参数,如果 USE_L10NFalse,则默认输入格式来自 DATE_INPUT_FORMATS,如果启用了本地化,则默认输入格式来自激活的的本地格式 DATE_INPUT_FORMATS 键。也请参见 格式本地化

DateTimeField

class DateTimeField(**kwargs)

  • 默认部件:DateTimeInput
  • 空值:None
  • 规范化为:Python 的 datetime.datetime 对象。
  • 验证给定的值是 datetime.datetimedatetime.date 或以特定日期时间格式化的字符串。
  • 错误信息键:requiredinvalid

需要一个可选的参数:

  • input_formats

    一个用于尝试将字符串转换为有效的 datetime.datetime 对象的格式迭代器,除了 ISO 8601 格式。

该字段始终接受 ISO 8601 格式的日期或类似于 parse_datetime() 可识别的日期字符串。以下是一些示例:

  • '2006-10-25 14:30:59'
  • '2006-10-25T14:30:59'
  • '2006-10-25 14:30'
  • '2006-10-25T14:30'
  • '2006-10-25T14:30Z'
  • '2006-10-25T14:30+02:00'
  • '2006-10-25'

如果没有提供 input_formats 参数,默认的输入格式来自 DATETIME_INPUT_FORMATSDATE_INPUT_FORMATS,如果: setting:USE_L10N 为 False,如果启用了本地化,则从激活的本地格式 DATETIME_INPUT_FORMATSDATE_INPUT_FORMATS 键中获取。也请参见 格式本地化

DecimalField

class DecimalField(**kwargs)

  • Field.localizeFalse 时是 NumberInput 否则,该字段的默认表单部件是 TextInput
  • 空值:None
  • 规范化为:Python 的 decimal
  • 验证给定的值是否为十进制数。如果提供了 max_valuemin_value,则使用 MaxValueValidatorMinValueValidator。如果提供了 step_size,则使用 StepValueValidator。前导和尾随空格会被忽略。
  • 错误消息键: required, invalid, max_value, min_value, max_digits, max_decimal_places, max_whole_digits, step_size

max_valuemin_value 错误信息可能包含 %(limit_value)s,将用适当的限制代替。同样,max_digitsmax_decimal_placesmax_whole_digits 错误信息可能包含 %(max)s

接受五个可选参数:

  • max_value

  • min_value

    这些控制着字段中允许的数值范围,应以 decimal.Decimal 值的形式给出。

  • max_digits

    值中允许的最大数字(小数点前的数字加上小数点后的数字,去掉前导零)。

  • decimal_places

    允许的最大小数位数。

  • step_size

    将有效输入限制为 step_size 的整数倍。

Changed in Django 4.1:

添加了 step_size 参数。

DurationField

class DurationField(**kwargs)

接受 parse_duration() 理解的任何格式。

EmailField

class EmailField(**kwargs)

  • 默认部件:EmailInput
  • 空值:不管你给 empty_value 的是什么。
  • 规范化为:一个字符串。
  • 使用 EmailValidator 来验证给定的值是一个有效的电子邮件地址,使用一个适度复杂的正则表达式。
  • 错误信息键:requiredinvalid

具有可选参数 max_lengthmin_lengthempty_value,它们的工作方式与 CharField 相同。max_length 参数默认为 320(参见 RFC 3696#section-3)。

Changed in Django 3.2.20:

max_length 的默认值已更改为 320 个字符。

FileField

class FileField(**kwargs)

  • 默认部件:ClearableFileInput
  • 空值:None
  • 规范化为:一个 UploadedFile 对象,它将文件内容和文件名包装成一个单一对象。
  • 可以验证非空文件数据已经绑定到表单中。
  • 错误信息键:requiredinvalidmissingemptymax_length

具有可选的验证参数:max_lengthallow_empty_file。如果提供了这些参数,它们确保文件名最多为给定的长度,并且即使文件内容为空,验证也将成功。

要了解更多关于 UploadedFile 对象的信息,请看 文件上传文档

当你在表单中使用 FileField 时,你还必须记住 将文件数据绑定到表单中

max_length 错误指的是文件名的长度。在该键的错误信息中,%(max)d 将被替换为最大文件名长度,%(length)d 将被替换为当前文件名长度。

FilePathField

class FilePathField(**kwargs)

  • 默认部件:Select
  • 空值:'' (空字符串)
  • 规范化为:一个字符串。
  • 验证选择是否存在于选择列表中。
  • 错误信息键:requiredinvalid_choice

该字段允许从某个目录内的文件中选择。它需要五个额外的参数;只有 path 是必须的。

  • path

    你想要列出的内容的目录的绝对路径。该目录必须存在。

  • recursive

    如果 False (默认),只提供 path 的直接内容作为选择。如果 True,目录将被递归递进,所有的子目录将被列为选择。

  • match

    正则表达式模式;只允许将名称与此表达式相匹配的文件作为选择。

  • allow_files

    可选。 可选 TrueFalse。 默认值是 True。 指定是否应该包含指定位置的文件。 此项或 allow_folders 必须为 True

  • allow_folders

    可选。 可选 TrueFalse。 默认为 False。 指定是否应包括指定位置的文件夹。 此项或 allow_files 必须为 True

FloatField

class FloatField(**kwargs)

  • Field.localizeFalse 时是 NumberInput 否则,该字段的默认表单部件是 TextInput
  • 空值:None
  • 规范化为:Python 的浮点数。
  • 验证给定的值是否为浮点数。如果提供了 max_valuemin_value,则使用 MaxValueValidatorMinValueValidator。如果提供了 step_size,则使用 StepValueValidator。允许前导和尾随空格,就像 Python 的 float() 函数一样。
  • 错误消息键: required, invalid, max_value, min_value, step_size

接受三个可选参数:

  • max_value

  • min_value

    这些控制了该字段允许的数值范围。

  • step_size

    New in Django 4.1.

    将有效输入限制为 step_size 的整数倍。

GenericIPAddressField

class GenericIPAddressField(**kwargs)

一个包含 IPv4 或 IPv6地址 的字段。

  • 默认部件:TextInput
  • 空值:'' (空字符串)
  • 规范化为:一个字符串。IPv6 地址的规范化如下所述。
  • 验证给定的值是一个有效的 IP 地址。
  • 错误信息键:requiredinvalid

IPv6 地址规范化遵循 RFC 4291#section-2.2 第 2.2 节,包括使用该节第 3 段建议的 IPv4 格式,如 ::fffff:192.0.2.0。例如,2001:0::0:01 将被标准化为 2001::1::fffff:0a0a:0a0a 将被标准化为 ::fffff:10.10.10.10。所有字符都转换为小写。

需要两个可选的参数:

  • protocol

    将有效输入限制为指定协议。接受的值是 both (默认)、IPv4IPv6。匹配是不区分大小写的。

  • unpack_ipv4

    解压 IPv4 映射地址,如 ::fffff:192.0.2.1。如果启用该选项,该地址将被解压为 192.0.2.1。默认为禁用。只有当 protocol 设置为 'both' 时才会启用。

ImageField

class ImageField(**kwargs)

  • 默认部件:ClearableFileInput
  • 空值:None
  • 规范化为:一个 UploadedFile 对象,它将文件内容和文件名包装成一个单一对象。
  • 验证文件数据是否已经绑定到表单中。同时使用 FileExtensionValidator 来验证 Pillow 是否支持文件扩展名。
  • 错误信息键:requiredinvalidmissingemptyinvalid_image

使用 ImageField 需要安装的 Pillow 支持你使用的图片格式。如果你在上传图片时遇到 corrupt image 错误,通常意味着 Pillow 不理解图片格式。要解决这个问题,请安装相应的库并重新安装 Pillow。

当你在表单中使用 ImageField 时,你还必须记住 将文件数据绑定到表单

在字段被清理和验证后,UploadedFile 对象将具有一个额外的 image 属性,其中包含 Pillow 的 Image 实例,用于检查文件是否为有效的图像。Pillow 在验证图像后关闭底层文件描述符,因此虽然可以访问非图像数据属性,如 formatheightwidth,但不能在不重新打开文件的情况下使用访问底层图像数据的方法,比如 getdata()getpixel()。例如:

  1. >>> from PIL import Image
  2. >>> from django import forms
  3. >>> from django.core.files.uploadedfile import SimpleUploadedFile
  4. >>> class ImageForm(forms.Form):
  5. ... img = forms.ImageField()
  6. ...
  7. >>> file_data = {"img": SimpleUploadedFile("test.png", b"file data")}
  8. >>> form = ImageForm({}, file_data)
  9. # Pillow closes the underlying file descriptor.
  10. >>> form.is_valid()
  11. True
  12. >>> image_field = form.cleaned_data["img"]
  13. >>> image_field.image
  14. <PIL.PngImagePlugin.PngImageFile image mode=RGBA size=191x287 at 0x7F5985045C18>
  15. >>> image_field.image.width
  16. 191
  17. >>> image_field.image.height
  18. 287
  19. >>> image_field.image.format
  20. 'PNG'
  21. >>> image_field.image.getdata()
  22. # Raises AttributeError: 'NoneType' object has no attribute 'seek'.
  23. >>> image = Image.open(image_field)
  24. >>> image.getdata()
  25. <ImagingCore object at 0x7f5984f874b0>

此外,UploadedFile.content_type 如果 Pillow 能够确定图片的内容类型,则会以图片的内容类型进行更新,否则会设置为 None

IntegerField

class IntegerField(**kwargs)

  • Field.localizeFalse 时是 NumberInput 否则,该字段的默认表单部件是 TextInput
  • 空值:None
  • 规范化为:Python 的整数。
  • 验证给定的值是否为整数。如果提供了 max_valuemin_value,则使用 MaxValueValidatorMinValueValidator。如果提供了 step_size,则使用 StepValueValidator。允许前导和尾随空格,就像 Python 的 int() 函数一样。
  • 错误消息键: required, invalid, max_value, min_value, step_size

max_valuemin_valuestep_size 的错误消息可能包含 %(limit_value)s,它将被适当的限制值替换。

接受三个可选的验证参数:

  • max_value

  • min_value

    这些控制了该字段允许的数值范围。

  • step_size

    New in Django 4.1.

    将有效输入限制为 step_size 的整数倍。

JSONField

class JSONField(encoder=None, decoder=None, **kwargs)

一个接受 JSON 编码数据的字段 JSONField

  • 默认部件:Textarea
  • 空值:None
  • 规范化为:JSON 值的 Python 表示(通常为 dictlistNone),取决于 JSONField.decoder
  • 验证给定值是否为有效的 JSON。
  • 错误信息键:requiredinvalid

需要两个可选的参数:

  • encoder

    一个 json.JSONEncoder 子类,用于序列化标准 JSON 序列器不支持的数据类型(例如 datetime.datetimeUUID)。例如,你可以使用 DjangoJSONEncoder 类。

    默认为 json.JSONEncoder

  • decoder

    一个 json.JSONDecoder 子类来反序列化输入。你的反序列化可能需要考虑到你无法确定输入类型的事实。例如,你有可能返回一个 datetime,但实际上是一个字符串,而这个字符串恰好与 datetime 的格式相同。

    decoder 可用于验证输入。如果在反序列化过程中出现 json.JSONONDecodeError,则会出现 ValidationError

    默认为 json.JSONDecoder

备注

如果你使用 ModelForm,将使用 JSONField 中的 encoderdecoder

用户友好的表单

JSONField 在大多数情况下不是特别方便用户使用。但是,它是一种有用的方式,可以将客户端部件的数据格式化,以便提交给服务器。

MultipleChoiceField

class MultipleChoiceField(**kwargs)

  • 默认部件:SelectMultiple
  • 空值:[] (空列表)
  • 规范化为:一个字符串列表。
  • 验证给定值列表中的每个值是否存在于选择列表中。
  • 错误信息键:requiredinvalid_choiceinvalid_list

invalid_choice 错误信息可能包含 %(value)s,该信息将被替换为选定的选择。

ChoiceField 一样,多了一个必要参数 choices

NullBooleanField

class NullBooleanField(**kwargs)

  • 默认部件:NullBooleanSelect
  • 空值:None
  • 规范化为:Python 的 TrueFalseNone 值。
  • 不验证任何东西(也就是说,它从不引起 ValidationError)。

NullBooleanField 可以通过提供部件 choices 来与诸如 SelectRadioSelect 等部件一起使用。

  1. NullBooleanField(
  2. widget=Select(
  3. choices=[
  4. ("", "Unknown"),
  5. (True, "Yes"),
  6. (False, "No"),
  7. ]
  8. )
  9. )

RegexField

class RegexField(**kwargs)

  • 默认部件:TextInput
  • 空值:不管你给 empty_value 的是什么。
  • 规范化为:一个字符串。
  • 使用 RegexValidator 来验证给定的值是否匹配某个正则表达式。
  • 错误信息键:requiredinvalid

需要一个额外的参数:

  • regex

    一个正则表达式,可以是字符串,也可以是编译后的正则表达式对象。

也接受 max_lengthmin_lengthstripempty_value,它们的工作原理和 CharField 一样。

  • strip

    默认值为 False。如果启用,将在验证正则表达式之前进行 strip。

SlugField

class SlugField(**kwargs)

这个字段用于在表单中表示一个模型 SlugField

需要两个可选的参数:

  • allow_unicode

    一个布尔值,指示该字段除了接受 ASCII 字母外,还接受 Unicode 字母。默认值为 False

  • empty_value

    用来表示“空”的值。默认为空字符串。

TimeField

class TimeField(**kwargs)

  • 默认部件:TimeInput
  • 空值:None
  • 规范化为:Python 的 datetime.time 对象。
  • 验证给定值是 datetime.time 或以特定时间格式化的字符串。
  • 错误信息键:requiredinvalid

需要一个可选的参数:

  • input_formats

    一个用于尝试将字符串转换为有效的 datetime.time 对象的格式迭代器。

如果没有提供 input_formats 参数,如果 USE_L10NFalse,则默认输入格式来自 TIME_INPUT_FORMATS` ,如果启用了本地化,则来自激活的本地格式 TIME_INPUT_FORMATS 键。也请参见 格式本地化

TypedChoiceField

class TypedChoiceField(**kwargs)

就像 ChoiceField 一样,除了 TypedChoiceField 需要两个额外的参数 coerceempty_value

  • 默认部件:Select
  • 空值:不管你给 empty_value 的是什么。
  • 规范化为:coerce 参数提供的类型的值。
  • 验证给定的值是否存在于选择列表中,并且可以被强制执行。
  • 错误信息键:requiredinvalid_choice

需要额外的参数:

  • coerce

    接受一个参数并返回一个强制值的函数。例子包括内置的 intfloatbool 和其他类型。默认为身份函数。请注意,强制执行发生在输入验证之后,所以可以强制执行到一个不存在于``choices``中的值。

  • empty_value

    用来表示“空”的值。默认为空字符串;None 是另一种常见的选择。请注意,这个值不会被 coerce 参数中给出的函数强制执行,所以要据此选择。

TypedMultipleChoiceField

class TypedMultipleChoiceField(**kwargs)

就像 MultipleChoiceField 一样,只是 TypedMultipleChoiceField 需要两个额外的参数:coerceempty_value

  • 默认部件:SelectMultiple
  • 空值:不管你给 empty_value 的是什么。
  • 归法化为:coerce 参数提供的类型值列表。
  • 验证给定的值是否存在于选择列表中,并且可以被强制执行。
  • 错误信息键:requiredinvalid_choice

invalid_choice 错误信息可能包含 %(value)s,该信息将被替换为选定的选择。

需要两个额外的参数,coerceempty_value,如 TypedChoiceField

URLField

class URLField(**kwargs)

  • 默认部件:URLInput
  • 空值:不管你给 empty_value 的是什么。
  • 规范化为:一个字符串。
  • 使用 URLValidator 来验证给定值是一个有效的 URL。
  • 错误信息键:requiredinvalid

具有可选参数 max_lengthmin_lengthempty_value,它们的工作方式与 CharField 相同。

UUIDField

class UUIDField(**kwargs)

  • 默认部件:TextInput
  • 空值:None
  • 规范化为:UUID 对象。
  • 错误信息键:requiredinvalid

该字段将接受作为 UUID 构造函数的 hex 参数的任何字符串格式。

稍复杂的内置 Field

ComboField

class ComboField(**kwargs)

  • 默认部件:TextInput
  • 空值:'' (空字符串)
  • 规范化为:一个字符串。
  • 根据 ComboField 参数指定的每个字段验证给定值。
  • 错误信息键:requiredinvalid

需要一个额外的必要参数。

  • fields

    应该用来验证字段值的字段列表(按照提供的顺序)。

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

MultiValueField

class MultiValueField(fields=(), **kwargs)

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

将多个字段的逻辑聚合在一起产生一个值。

这个字段是抽象的,必须被子类化。与单值字段相反, MultiValueField 的子类不能实现 clean(),而是——实现 compress()

需要一个额外的必要参数。

  • fields

    字段组成的元组,其值经清理后合并为一个值。 字段的每个值都由 fields 中的相应字段进行清理——第一个值由第一个字段清理,第二个值由第二个字段清理,等等。当所有字段清理完毕后,通过 compress() 将清理后的值列表合并为一个值。

还需要一些可选的参数:

  • require_all_fields

    默认值为 True,在这种情况下,如果没有为任何字段提供值,就会出现 required 验证错误。

    Field.required 属性设置为 False 时,可将单个字段设置为 False,使其成为可选字段。如果没有为必填字段提供任何值,就会出现 incomplete 的验证错误。

    可以在 MultiValueField 子类上定义一个默认的 incomplete 错误信息,也可以在每个单独的字段上定义不同的信息。例如:

    ``` from django.core.validators import RegexValidator

  1. class PhoneField(MultiValueField):
  2. def __init__(self, **kwargs):
  3. # Define one message for all fields.
  4. error_messages = {
  5. "incomplete": "Enter a country calling code and a phone number.",
  6. }
  7. # Or define a different message for each field.
  8. fields = (
  9. CharField(
  10. error_messages={"incomplete": "Enter a country calling code."},
  11. validators=[
  12. RegexValidator(r"^[0-9]+$", "Enter a valid country calling code."),
  13. ],
  14. ),
  15. CharField(
  16. error_messages={"incomplete": "Enter a phone number."},
  17. validators=[RegexValidator(r"^[0-9]+$", "Enter a valid phone number.")],
  18. ),
  19. CharField(
  20. validators=[RegexValidator(r"^[0-9]+$", "Enter a valid extension.")],
  21. required=False,
  22. ),
  23. )
  24. super().__init__(
  25. error_messages=error_messages,
  26. fields=fields,
  27. require_all_fields=False,
  28. **kwargs
  29. )
  30. ```
  • widget

    必须是 django.forms.MultiWidget 的子类。默认值是 TextInput,在这种情况下可能不是很有用。

  • compress(data_list)

    取一个有效值的列表,并返回这些值的“压缩”版本——在一个单一值中。例如,SplitDateTimeField 是一个子类,它将一个时间字段和一个日期字段合并成一个 datetime 对象。

    这个方法必须在子类中实现。

SplitDateTimeField

class SplitDateTimeField(**kwargs)

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

需要两个可选的参数:

  • input_date_formats

    用于将字符串转换为有效的 datetime.date 对象的格式列表。

如果没有提供 input_date_formats 参数,则使用 DateField 的默认输入格式。

  • input_time_formats

    用于将字符串转换为有效的 datetime.time 对象的格式列表。

如果没有提供 input_time_formats 参数,则使用 TimeField 的默认输入格式。

处理关系的字段

有两个字段可用于表示模型之间的关系: ModelChoiceFieldModelMultipleChoiceField。 这两个字段都需要一个 queryset 参数,用于创建字段的选择。 在表单验证后,这些字段将把一个模型对象(对于 ModelChoiceField)或多个模型对象(对于 ModelMultipleChoiceField)放入表单的 cleaned_data 字典中。

对于更复杂的用途,你可以在声明表单字段时指定 queryset=None,然后在表单的 __init__() 方法中填充 queryset

  1. class FooMultipleChoiceForm(forms.Form):
  2. foo_select = forms.ModelMultipleChoiceField(queryset=None)
  3. def __init__(self, *args, **kwargs):
  4. super().__init__(*args, **kwargs)
  5. self.fields["foo_select"].queryset = ...

ModelChoiceFieldModelMultipleChoiceField 都有一个 iterator 属性,它指定了在生成选择时用于迭代查询集的类。详见 迭代关系选择

ModelChoiceField

class ModelChoiceField(**kwargs)

  • 默认部件:Select
  • 空值:None
  • 规范化为:一个模型实例。
  • 验证给定的 id 是否存在于查询集中。
  • 错误信息键:requiredinvalid_choice

invalid_choice 错误信息可能包含 %(value)s,该信息将被替换为选定的选择。

允许选择一个单一的模型对象,适合代表一个外键。请注意,当条目数量增加时,ModelChoiceField 的默认部件变得不实用。你应该避免将其用于超过 100 个项目。

需要一个参数:

  • queryset

    由模型对象组成的 QuerySet,从中得出字段的选择,用于验证用户的选择。它在表单渲染时被执行。

ModelChoiceField 还接受几个可选参数:

  • empty_label

    默认情况下,ModelChoiceField 使用的 <select> 小组件将在列表顶部有一个空的选择。你可以用 empty_label 属性来改变这个标签的文本(默认是 "---------"),或者你可以通过将 empty_label 设置为 None 来完全禁用空标签。

    1. # A custom empty label
    2. field1 = forms.ModelChoiceField(queryset=..., empty_label="(Nothing)")
    3. # No empty label
    4. field2 = forms.ModelChoiceField(queryset=..., empty_label=None)

    请注意,如果 ModelChoiceField 是必填的并且具有默认的初始值,或者 widget 设置为 RadioSelect 并且 ModelChoiceField.blank 参数为 False,则不会创建空选择项(无论 empty_label 的值如何)。

  • to_field_name

    这个可选参数用于指定字段,作为字段的小组件中选择的值。请确保它是模型的唯一字段,否则所选的值可能会匹配多个对象。默认情况下,它被设置为 None,在这种情况下,将使用每个对象的主键。例如:

    1. # No custom to_field_name
    2. field1 = forms.ModelChoiceField(queryset=...)

    会产生:

    1. <select id="id_field1" name="field1">
    2. <option value="obj1.pk">Object1</option>
    3. <option value="obj2.pk">Object2</option>
    4. ...
    5. </select>

    和:

    1. # to_field_name provided
    2. field2 = forms.ModelChoiceField(queryset=..., to_field_name="name")

    会产生:

    1. <select id="id_field2" name="field2">
    2. <option value="obj1.name">Object1</option>
    3. <option value="obj2.name">Object2</option>
    4. ...
    5. </select>
  • blank

    在使用 RadioSelect 小部件时,这个可选的布尔参数确定是否创建一个空选择项。默认情况下,blankFalse,在这种情况下不会创建空选择项。

ModelChoiceField 也有属性:

  • iterator

    用于从 queryset 中生成字段选择的迭代器类。默认情况下, ModelChoiceIterator

模型的 __str__() 方法将被调用,以生成用于字段选择的对象的字符串表示。要提供自定义的表示,请将 ModelChoiceField 子类化,并覆盖 label_from_instance。该方法将接收一个模型对象,并应返回一个适合表示它的字符串。例如:

  1. from django.forms import ModelChoiceField
  2. class MyModelChoiceField(ModelChoiceField):
  3. def label_from_instance(self, obj):
  4. return "My Object #%i" % obj.id

ModelMultipleChoiceField

class ModelMultipleChoiceField(**kwargs)

  • 默认部件:SelectMultiple
  • 空值:一个空的 QuerySetself.queryset.none())。
  • 规范化为:一个模型实例的 QuerySet
  • 验证给定值列表中的每个 id 是否存在于查询集中。
  • 错误信息键:requiredinvalid_listinvalid_choiceinvalid_pk_value

invalid_choice 信息可能包含 %(value)sinvalid_pk_value 信息可能包含 %(pk)s,将用适当的值代替。

允许选择一个或多个模型对象,适合表示多对多关系。与 ModelChoiceField 一样,你可以使用 label_from_instance 来自定义对象的表示。

需要一个参数:

需要一个可选的参数:

ModelMultipleChoiceField 也有属性:

迭代关系选择

默认情况下, ModelChoiceFieldModelMultipleChoiceField 使用 ModelChoiceIterator 来生成它们的字段 choices

当迭代时,ModelChoiceIterator 产生一个二元元组选择,包含 ModelChoiceIteratorValue 实例作为每个选择的第一个 value 元素。ModelChoiceIteratorValue 封装了选择值,同时保持了对源模型实例的引用,可用于自定义部件的实现,例如,将 data-* attributes 添加到 <option>

例如,考虑以下模型:

  1. from django.db import models
  2. class Topping(models.Model):
  3. name = models.CharField(max_length=100)
  4. price = models.DecimalField(decimal_places=2, max_digits=6)
  5. def __str__(self):
  6. return self.name
  7. class Pizza(models.Model):
  8. topping = models.ForeignKey(Topping, on_delete=models.CASCADE)

你可以使用 Select 部件子类将 Topping.price 的值作为 HTML 属性 data-price,包含在每个 <option> 元素中:

  1. from django import forms
  2. class ToppingSelect(forms.Select):
  3. def create_option(
  4. self, name, value, label, selected, index, subindex=None, attrs=None
  5. ):
  6. option = super().create_option(
  7. name, value, label, selected, index, subindex, attrs
  8. )
  9. if value:
  10. option["attrs"]["data-price"] = value.instance.price
  11. return option
  12. class PizzaForm(forms.ModelForm):
  13. class Meta:
  14. model = Pizza
  15. fields = ["topping"]
  16. widgets = {"topping": ToppingSelect}

这将使 Pizza.topping 选择为:

  1. <select id="id_topping" name="topping" required>
  2. <option value="" selected>---------</option>
  3. <option value="1" data-price="1.50">mushrooms</option>
  4. <option value="2" data-price="1.25">onions</option>
  5. <option value="3" data-price="1.75">peppers</option>
  6. <option value="4" data-price="2.00">pineapple</option>
  7. </select>

对于更高级的用法,你可以将 ModelChoiceIterator 子类化,以自定义产生的二元元组选择。

ModelChoiceIterator

class ModelChoiceIterator(field)

指定给 ModelChoiceField`和:class:`ModelMultipleChoiceFielditerator 属性的默认类。迭代器,从查询集中产生二元元组选择。

需要一个参数:

  • field

    ModelChoiceFieldModelMultipleChoiceField 的实例来迭代和产生选择。

ModelChoiceIter 有以下方法:

  • __iter__()

    产生二元元组选择,格式为 ChoiceField.chips 使用的 (value, label)。第一个 value 元素是一个 ModelChoiceIteratorValue 实例。

ModelChoiceIteratorValue

class ModelChoiceIteratorValue(value, instance)

需要两个参数:

  • value

    选择的值。该值用于呈现 HTML <option> 元素的 value 属性。

  • instance

    来自查询集的模型实例。该实例可以在自定义的 ChoiceWidget.create_option() 实现中被访问,以调整渲染的 HTML。

ModelChoiceIteratorValue 有以下方法:

  • __str__()

    返回 value 作为一个字符串在 HTML 中显示。

创建自定义字段

如果内置的 Field 类不能满足你的需求,你可以创建自定义的 Field 类。为此,创建一个 django.forms.Field 的子类。它唯一的要求是实现一个 clean() 方法,并且它的 __init__() 方法接受上面提到的核心参数 (required, label, initial, widget, help_text)。

你也可以通过覆盖 get_bound_field() 来自定义字段的访问方式。