小部件

小部件是 Django 对 HTML 输入元素的表示。小部件负责处理 HTML 的渲染以及从与小部件对应的 GET/POST 字典中提取数据。

内置小部件生成的 HTML 使用 HTML5 语法,目标是 <!DOCTYPE html>。例如,它使用布尔属性,例如 checked,而不是 XHTML 风格的 checked='checked'

提示

小部件不应与 表单字段 混淆。表单字段处理输入验证的逻辑,并在模板中直接使用。小部件处理网页上 HTML 表单输入元素的渲染以及原始提交数据的提取。但是,小部件确实需要 分配 给表单字段。

指定小部件

每当您在表单上指定字段时,Django 将使用适合要显示的数据类型的默认小部件。要查找哪个字段使用哪个小部件,请参阅有关 内置字段类 的文档。

但是,如果您想为字段使用不同的窗口小部件,可以使用 widget 字段定义上的参数。例如

from django import forms


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

这将指定一个表单,其中包含一个使用较大的 Textarea 小部件的注释,而不是默认的 TextInput 小部件。

为小部件设置参数

许多小部件具有可选的额外参数;它们可以在字段上定义小部件时设置。在以下示例中,years 属性设置为 SelectDateWidget

from django import forms

BIRTH_YEAR_CHOICES = ["1980", "1981", "1982"]
FAVORITE_COLORS_CHOICES = {
    "blue": "Blue",
    "green": "Green",
    "black": "Black",
}


class SimpleForm(forms.Form):
    birth_year = forms.DateField(
        widget=forms.SelectDateWidget(years=BIRTH_YEAR_CHOICES)
    )
    favorite_colors = forms.MultipleChoiceField(
        required=False,
        widget=forms.CheckboxSelectMultiple,
        choices=FAVORITE_COLORS_CHOICES,
    )

有关哪些小部件可用以及它们接受哪些参数的更多信息,请参阅 内置小部件

Select 小部件继承的小部件

Select 小部件继承的小部件处理选项。它们向用户提供一个选项列表供选择。不同的窗口小部件以不同的方式呈现此选择;Select 小部件本身使用 <select> HTML 列表表示,而 RadioSelect 使用单选按钮。

Select 小部件默认情况下在 ChoiceField 字段上使用。小部件上显示的选项继承自 ChoiceField,更改 ChoiceField.choices 将更新 Select.choices。例如

>>> from django import forms
>>> CHOICES = {"1": "First", "2": "Second"}
>>> choice_field = forms.ChoiceField(widget=forms.RadioSelect, choices=CHOICES)
>>> choice_field.choices
[('1', 'First'), ('2', 'Second')]
>>> choice_field.widget.choices
[('1', 'First'), ('2', 'Second')]
>>> choice_field.widget.choices = []
>>> choice_field.choices = [("1", "First and only")]
>>> choice_field.widget.choices
[('1', 'First and only')]

但是,提供 choices 属性的小部件可以与不基于选择的字段一起使用——例如 CharField——但建议在选项固有地属于模型而不是仅仅是表示小部件时使用基于 ChoiceField 的字段。

自定义小部件实例

当 Django 将小部件渲染为 HTML 时,它只渲染非常少的标记——Django 不会添加类名或任何其他特定于小部件的属性。这意味着,例如,所有 TextInput 小部件在您的网页上看起来都一样。

有两种方法可以自定义小部件:每个小部件实例每个小部件类

样式化小部件实例

如果您想让一个小部件实例看起来与另一个不同,您需要在实例化小部件对象并将其分配给表单字段时指定其他属性(并且可能在您的 CSS 文件中添加一些规则)。

例如,考虑以下表单

from django import forms


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

此表单将包含三个默认的 TextInput 小部件,具有默认渲染——没有 CSS 类,没有额外属性。这意味着为每个小部件提供的输入框将以完全相同的方式渲染

>>> f = CommentForm(auto_id=False)
>>> print(f)
<div>Name:<input type="text" name="name" required></div>
<div>Url:<input type="url" name="url" required></div>
<div>Comment:<input type="text" name="comment" required></div>

在真实的网页上,您可能不希望每个小部件看起来都一样。您可能希望为注释提供一个更大的输入元素,并且您可能希望“name”小部件具有某些特殊的 CSS 类。还可以指定“type”属性以利用新的 HTML5 输入类型。为此,您使用 Widget.attrs 创建小部件时的参数

class CommentForm(forms.Form):
    name = forms.CharField(widget=forms.TextInput(attrs={"class": "special"}))
    url = forms.URLField()
    comment = forms.CharField(widget=forms.TextInput(attrs={"size": "40"}))

您也可以在表单定义中修改小部件

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

    name.widget.attrs.update({"class": "special"})
    comment.widget.attrs.update(size="40")

或者,如果字段不是直接在表单上声明的(例如模型表单字段),您可以使用 Form.fields 属性

class CommentForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["name"].widget.attrs.update({"class": "special"})
        self.fields["comment"].widget.attrs.update(size="40")

然后,Django 将在渲染的输出中包含这些额外属性

>>> f = CommentForm(auto_id=False)
>>> print(f)
<div>Name:<input type="text" name="name" class="special" required></div>
<div>Url:<input type="url" name="url" required></div>
<div>Comment:<input type="text" name="comment" size="40" required></div>

您还可以使用 attrs 设置 HTML id。有关示例,请参阅 BoundField.id_for_label

样式化小部件类

对于小部件,可以添加资产 (cssjavascript) 并更深入地自定义它们的外观和行为。

简而言之,您需要子类化小部件,并 定义一个“Media”内部类创建一个“media”属性

这些方法涉及一些高级的 Python 编程,并在 表单资产 主题指南中进行了详细描述。

基本小部件类

基本小部件类 WidgetMultiWidget 是所有 内置小部件 的子类,可以作为自定义小部件的基础。

Widget

class Widget(attrs=None)

此抽象类无法渲染,但提供基本属性 attrs。您也可以在自定义小部件上实现或覆盖 render() 方法。

attrs

一个字典,包含要在渲染的小部件上设置的 HTML 属性。

>>> from django import forms
>>> name = forms.TextInput(attrs={"size": 10, "title": "Your name"})
>>> name.render("name", "A name")
'<input title="Your name" type="text" name="name" value="A name" size="10">'

如果您将 TrueFalse 的值分配给属性,它将被渲染为 HTML5 布尔属性

>>> name = forms.TextInput(attrs={"required": True})
>>> name.render("name", "A name")
'<input name="name" type="text" value="A name" required>'
>>>
>>> name = forms.TextInput(attrs={"required": False})
>>> name.render("name", "A name")
'<input name="name" type="text" value="A name">'
supports_microseconds

一个属性,默认为 True。如果设置为 False,则 datetimetime 值的微秒部分将设置为 0

format_value(value)

清理并返回一个值,用于小部件模板。value 不保证是有效的输入,因此子类实现应该进行防御性编程。

get_context(name, value, attrs)

返回一个字典,其中包含渲染小部件模板时要使用的值。默认情况下,字典包含一个键,'widget',它是一个包含以下键的小部件字典表示形式

  • 'name': 来自 name 参数的字段名称。
  • 'is_hidden': 一个布尔值,指示此小部件是否隐藏。
  • 'required': 一个布尔值,指示此小部件的字段是否必填。
  • 'value': 由 format_value() 返回的值。
  • 'attrs': 要在渲染的小部件上设置的 HTML 属性。 attrs 属性和 attrs 参数的组合。
  • 'template_name': self.template_name 的值。

Widget 子类可以通过覆盖此方法提供自定义上下文值。

id_for_label(id_)

返回此小部件的 HTML ID 属性,供 <label> 使用,给定字段的 ID。如果 ID 不可用,则返回空字符串。

此钩子是必要的,因为某些小部件具有多个 HTML 元素,因此具有多个 ID。在这种情况下,此方法应返回与小部件标签中的第一个 ID 相对应的 ID 值。

render(name, value, attrs=None, renderer=None)

使用给定的渲染器将小部件渲染为 HTML。如果 rendererNone,则使用 FORM_RENDERER 设置中的渲染器。

value_from_datadict(data, files, name)

给定一个数据字典和此小部件的名称,返回此小部件的值。 files 可能包含来自 request.FILES 的数据。如果未提供值,则返回 None。还要注意,在处理表单数据期间,可能会多次调用 value_from_datadict,因此,如果您对其进行自定义并添加昂贵的处理,则应自己实现一些缓存机制。

value_omitted_from_data(data, files, name)

给定 datafiles 字典以及此小部件的名称,返回此小部件是否有数据或文件。

该方法的结果会影响模型表单中的字段是否 回退到其默认值

特殊情况是 CheckboxInputCheckboxSelectMultipleSelectMultiple,它们始终返回 False,因为未选中的复选框和未选中的 <select multiple> 不会出现在 HTML 表单提交的数据中,因此无法确定用户是否提交了值。

use_fieldset

一个属性,用于标识小部件在渲染时是否应与 <legend> 一起分组在 <fieldset> 中。默认为 False,但当小部件包含多个 <input> 标签(如 CheckboxSelectMultipleRadioSelectMultiWidgetSplitDateTimeWidgetSelectDateWidget)时,为 True

use_required_attribute(initial)

给定表单字段的 initial 值,返回小部件是否可以使用 required HTML 属性进行渲染。表单使用此方法以及 Field.requiredForm.use_required_attribute 来确定是否为每个字段显示 required 属性。

默认情况下,对于隐藏的小部件返回 False,否则返回 True。特殊情况是 FileInputClearableFileInput,当 initial 设置时,它们返回 False,而 CheckboxSelectMultiple 始终返回 False,因为浏览器验证需要选中所有复选框,而不是至少选中一个。

在与浏览器验证不兼容的自定义小部件中覆盖此方法。例如,由隐藏的 textarea 元素支持的 WSYSIWG 文本编辑器小部件可能希望始终返回 False 以避免对隐藏字段进行浏览器验证。

MultiWidget

class MultiWidget(widgets, attrs=None)

一个由多个小部件组成的小部件。 MultiWidgetMultiValueField 协同工作。

MultiWidget 具有一个必需参数

widgets

包含所需小部件的可迭代对象。例如

>>> from django.forms import MultiWidget, TextInput
>>> widget = MultiWidget(widgets=[TextInput, TextInput])
>>> widget.render("name", ["john", "paul"])
'<input type="text" name="name_0" value="john"><input type="text" name="name_1" value="paul">'

您可以提供一个字典,以便为每个子小部件上的 name 属性指定自定义后缀。在这种情况下,对于每个 (key, widget) 对,键将附加到小部件的 name 以便生成属性值。您可以为单个键提供空字符串 (''),以抑制一个小部件的后缀。例如

>>> widget = MultiWidget(widgets={"": TextInput, "last": TextInput})
>>> widget.render("name", ["john", "paul"])
'<input type="text" name="name" value="john"><input type="text" name="name_last" value="paul">'

以及一个必需的方法

decompress(value)

此方法从字段获取单个“压缩”值,并返回一个“解压缩”值的列表。可以假定输入值有效,但不一定非空。

此方法必须由子类实现,并且由于该值可能为空,因此实现必须具有防御性。

“解压缩”背后的基本原理是,有必要将表单字段的组合值“拆分”为每个小部件的值。

一个例子是 SplitDateTimeWidget 如何将 datetime 值转换为一个列表,其中日期和时间被拆分为两个单独的值

from django.forms import MultiWidget


class SplitDateTimeWidget(MultiWidget):
    # ...

    def decompress(self, value):
        if value:
            return [value.date(), value.time()]
        return [None, None]

提示

请注意,MultiValueField 具有一个互补方法 compress(),它具有相反的职责 - 将所有成员字段的清理值组合成一个。

它提供了一些自定义上下文

get_context(name, value, attrs)

除了在Widget.get_context()中描述的'widget'键之外,MultiWidget还添加了一个widget['subwidgets']键。

这些可以在小部件模板中循环。

{% for subwidget in widget.subwidgets %}
    {% include subwidget.template_name with widget=subwidget %}
{% endfor %}

以下是一个子类化MultiWidget的小部件示例,用于以不同的选择框显示日期的日、月和年。此小部件旨在与DateField一起使用,而不是与MultiValueField一起使用,因此我们已经实现了value_from_datadict()

from datetime import date
from django import forms


class DateSelectorWidget(forms.MultiWidget):
    def __init__(self, attrs=None):
        days = {day: day for day in range(1, 32)}
        months = {month: month for month in range(1, 13)}
        years = {year: year for year in [2018, 2019, 2020]}
        widgets = [
            forms.Select(attrs=attrs, choices=days),
            forms.Select(attrs=attrs, choices=months),
            forms.Select(attrs=attrs, choices=years),
        ]
        super().__init__(widgets, attrs)

    def decompress(self, value):
        if isinstance(value, date):
            return [value.day, value.month, value.year]
        elif isinstance(value, str):
            year, month, day = value.split("-")
            return [day, month, year]
        return [None, None, None]

    def value_from_datadict(self, data, files, name):
        day, month, year = super().value_from_datadict(data, files, name)
        # DateField expects a single string that it can parse into a date.
        return "{}-{}-{}".format(year, month, day)

构造函数在列表中创建了几个Select小部件。 super()方法使用此列表来设置小部件。

必需的方法decompress()将一个datetime.date值分解为与每个小部件相对应的日、月和年值。如果选择了无效的日期,例如不存在的 2 月 30 日,则DateField会将字符串传递给此方法,因此需要解析。最后的return处理valueNone的情况,这意味着我们的子小部件没有默认值。

value_from_datadict()的默认实现返回一个与每个Widget相对应的值列表。这在使用MultiWidgetMultiValueField一起使用时是合适的。但由于我们希望将此小部件与DateField一起使用,后者接受单个值,因此我们覆盖了此方法。此处的实现将子小部件中的数据组合成DateField期望的格式的字符串。

内置小部件

Django 在django.forms.widgets模块中提供了所有基本 HTML 小部件的表示形式,以及一些常用的分组小部件,包括文本输入各种复选框和选择器上传文件处理多值输入

处理文本输入的小部件

这些小部件使用 HTML 元素inputtextarea

TextInput

class TextInput
  • input_type: 'text'
  • template_name: 'django/forms/widgets/text.html'
  • 呈现为:<input type="text" ...>

NumberInput

class NumberInput
  • input_type: 'number'
  • template_name: 'django/forms/widgets/number.html'
  • 呈现为:<input type="number" ...>

注意,并非所有浏览器都支持在number输入类型中输入本地化的数字。Django 本身避免将它们用于其localize属性设置为True的字段。

EmailInput

class EmailInput
  • input_type: 'email'
  • template_name: 'django/forms/widgets/email.html'
  • 呈现为:<input type="email" ...>

URLInput

class URLInput
  • input_type: 'url'
  • template_name: 'django/forms/widgets/url.html'
  • 呈现为:<input type="url" ...>

PasswordInput

class PasswordInput
  • input_type: 'password'
  • template_name: 'django/forms/widgets/password.html'
  • 呈现为:<input type="password" ...>

接受一个可选参数

render_value

确定在验证错误后表单重新显示时小部件是否将填充值(默认值为False)。

HiddenInput

class HiddenInput
  • input_type: 'hidden'
  • template_name: 'django/forms/widgets/hidden.html'
  • 呈现为:<input type="hidden" ...>

请注意,还有一个MultipleHiddenInput小部件,它封装了一组隐藏的输入元素。

DateInput

class DateInput
  • input_type: 'text'
  • template_name: 'django/forms/widgets/date.html'
  • 呈现为:<input type="text" ...>

接受与TextInput相同的参数,还有一个可选参数

format

此字段的初始值将以该格式显示。

如果没有提供format参数,则默认格式是DATE_INPUT_FORMATS中找到的第一个格式,并尊重格式本地化%U%W%j格式不受此小部件支持。

DateTimeInput

class DateTimeInput
  • input_type: 'text'
  • template_name: 'django/forms/widgets/datetime.html'
  • 呈现为:<input type="text" ...>

接受与TextInput相同的参数,还有一个可选参数

format

此字段的初始值将以该格式显示。

如果没有提供format参数,则默认格式是DATETIME_INPUT_FORMATS中找到的第一个格式,并尊重格式本地化%U%W%j格式不受此小部件支持。

默认情况下,时间值的微秒部分始终设置为0。如果需要微秒,请使用子类,并将supports_microseconds属性设置为True

TimeInput

class TimeInput
  • input_type: 'text'
  • template_name: 'django/forms/widgets/time.html'
  • 呈现为:<input type="text" ...>

接受与TextInput相同的参数,还有一个可选参数

format

此字段的初始值将以该格式显示。

如果未提供 format 参数,则默认格式为在 TIME_INPUT_FORMATS 中找到的第一个格式,并遵循 格式本地化

有关微秒的处理,请参见 DateTimeInput

Textarea

class Textarea
  • template_name: 'django/forms/widgets/textarea.html'
  • 渲染为:<textarea>...</textarea>

选择器和复选框小部件

这些小部件使用 HTML 元素 <select><input type="checkbox"><input type="radio">

渲染多个选项的小部件具有一个 option_template_name 属性,该属性指定用于渲染每个选项的模板。例如,对于 Select 小部件,select_option.html 渲染 <select><option>

CheckboxInput

class CheckboxInput
  • input_type: 'checkbox'
  • template_name: 'django/forms/widgets/checkbox.html'
  • 渲染为:<input type="checkbox" ...>

接受一个可选参数

check_test

一个可调用对象,它接受 CheckboxInput 的值并返回 True(如果应为该值选中复选框)。

Select

class Select
  • template_name: 'django/forms/widgets/select.html'
  • option_template_name: 'django/forms/widgets/select_option.html'
  • 渲染为:<select><option ...>...</select>
choices

当表单字段没有 choices 属性时,此属性是可选的。如果有,它将在 Field 上更新属性时覆盖您在此处设置的任何内容。

NullBooleanSelect

class NullBooleanSelect
  • template_name: 'django/forms/widgets/select.html'
  • option_template_name: 'django/forms/widgets/select_option.html'

具有“未知”、“是”和“否”选项的选择小部件

SelectMultiple

class SelectMultiple
  • template_name: 'django/forms/widgets/select.html'
  • option_template_name: 'django/forms/widgets/select_option.html'

类似于 Select,但允许多选:<select multiple>...</select>

RadioSelect

class RadioSelect
  • template_name: 'django/forms/widgets/radio.html'
  • option_template_name: 'django/forms/widgets/radio_option.html'

类似于 Select,但渲染为 <div> 标签内的单选按钮列表

<div>
  <div><input type="radio" name="..."></div>
  ...
</div>

为了更细致地控制生成的标记,您可以在模板中循环遍历单选按钮。假设一个表单 myform,它有一个使用 RadioSelect 作为其小部件的字段 beatles

<fieldset>
    <legend>{{ myform.beatles.label }}</legend>
    {% for radio in myform.beatles %}
    <div class="myradio">
        {{ radio }}
    </div>
    {% endfor %}
</fieldset>

这将生成以下 HTML

<fieldset>
    <legend>Radio buttons</legend>
    <div class="myradio">
        <label for="id_beatles_0"><input id="id_beatles_0" name="beatles" type="radio" value="john" required> John</label>
    </div>
    <div class="myradio">
        <label for="id_beatles_1"><input id="id_beatles_1" name="beatles" type="radio" value="paul" required> Paul</label>
    </div>
    <div class="myradio">
        <label for="id_beatles_2"><input id="id_beatles_2" name="beatles" type="radio" value="george" required> George</label>
    </div>
    <div class="myradio">
        <label for="id_beatles_3"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" required> Ringo</label>
    </div>
</fieldset>

其中包括 <label> 标签。为了更细致地控制,您可以使用每个单选按钮的 tagchoice_labelid_for_label 属性。例如,此模板…

<fieldset>
    <legend>{{ myform.beatles.label }}</legend>
    {% for radio in myform.beatles %}
    <label for="{{ radio.id_for_label }}">
        {{ radio.choice_label }}
        <span class="radio">{{ radio.tag }}</span>
    </label>
    {% endfor %}
</fieldset>

…将导致以下 HTML

<fieldset>
    <legend>Radio buttons</legend>
    <label for="id_beatles_0">
        John
        <span class="radio"><input id="id_beatles_0" name="beatles" type="radio" value="john" required></span>
    </label>
    <label for="id_beatles_1">
        Paul
        <span class="radio"><input id="id_beatles_1" name="beatles" type="radio" value="paul" required></span>
    </label>
    <label for="id_beatles_2">
        George
        <span class="radio"><input id="id_beatles_2" name="beatles" type="radio" value="george" required></span>
    </label>
    <label for="id_beatles_3">
        Ringo
        <span class="radio"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" required></span>
    </label>
</fieldset>

如果您决定不循环遍历单选按钮(例如,如果您的模板包含 {{ myform.beatles }}),它们将输出在 <div> 中,带有 <div> 标签,如上所示。

外部 <div> 容器接收小部件的 id 属性(如果已定义),否则接收 BoundField.auto_id

在循环遍历单选按钮时,labelinput 标签分别包含 forid 属性。每个单选按钮都有一个 id_for_label 属性来输出元素的 ID。

CheckboxSelectMultiple

class CheckboxSelectMultiple
  • template_name: 'django/forms/widgets/checkbox_select.html'
  • option_template_name: 'django/forms/widgets/checkbox_option.html'

类似于 SelectMultiple,但渲染为复选框列表

<div>
  <div><input type="checkbox" name="..." ></div>
  ...
</div>

外部 <div> 容器接收小部件的 id 属性(如果已定义),否则接收 BoundField.auto_id

RadioSelect 一样,您可以循环遍历小部件选项的各个复选框。与 RadioSelect 不同,如果字段是必需的,则复选框不会包含 required HTML 属性,因为浏览器验证将要求选中所有复选框而不是至少选中一个。

在循环遍历复选框时,labelinput 标签分别包含 forid 属性。每个复选框都有一个 id_for_label 属性来输出元素的 ID。

文件上传小部件

FileInput

class FileInput
  • template_name: 'django/forms/widgets/file.html'
  • 渲染为:<input type="file" ...>

ClearableFileInput

class ClearableFileInput
  • template_name: 'django/forms/widgets/clearable_file_input.html'
  • 渲染为:<input type="file" ...>,以及一个额外的复选框输入,用于清除字段的值(如果字段不是必需的并且具有初始数据)。

复合小部件

MultipleHiddenInput

class MultipleHiddenInput
  • template_name: 'django/forms/widgets/multiple_hidden.html'
  • 渲染为:多个 <input type="hidden" ...> 标签

一个小部件,用于处理具有值列表的字段的多个隐藏小部件。

SplitDateTimeWidget

class SplitDateTimeWidget
  • template_name: 'django/forms/widgets/splitdatetime.html'

使用 MultiWidget 包装两个小部件:DateInput 用于日期,TimeInput 用于时间。必须与 SplitDateTimeField 而不是 DateTimeField 一起使用。

SplitDateTimeWidget 有几个可选参数

date_format

类似于 DateInput.format

time_format

类似于 TimeInput.format

date_attrs
time_attrs

类似于 Widget.attrs。一个包含要设置在渲染的 DateInputTimeInput 小部件上的 HTML 属性的字典。如果未设置这些属性,则使用 Widget.attrs

SplitHiddenDateTimeWidget

class SplitHiddenDateTimeWidget
  • template_name: 'django/forms/widgets/splithiddendatetime.html'

类似于 SplitDateTimeWidget,但对日期和时间都使用 HiddenInput

SelectDateWidget

class SelectDateWidget
  • template_name: 'django/forms/widgets/select_date.html'

围绕三个 Select 小部件的包装器:每个小部件分别用于月、日和年。

接受几个可选参数

years

在“年”选择框中使用的可选年份列表/元组。默认值为包含当前年份和未来 9 年的列表。

months

在“月”选择框中使用的可选月份字典。

字典的键对应于月份编号(从 1 开始),值是显示的月份

MONTHS = {
    1: _("jan"),
    2: _("feb"),
    3: _("mar"),
    4: _("apr"),
    5: _("may"),
    6: _("jun"),
    7: _("jul"),
    8: _("aug"),
    9: _("sep"),
    10: _("oct"),
    11: _("nov"),
    12: _("dec"),
}
empty_label

如果 DateField 不是必需的,SelectDateWidget 将在列表顶部有一个空选项(默认情况下为 ---)。您可以使用 empty_label 属性更改此标签的文本。 empty_label 可以是 stringlisttuple。当使用字符串时,所有选择框将分别有一个带有此标签的空选项。如果 empty_label 是一个包含 3 个字符串元素的 listtuple,则选择框将有自己的自定义标签。标签应按此顺序排列 ('year_label', 'month_label', 'day_label')

# A custom empty label with string
field1 = forms.DateField(widget=SelectDateWidget(empty_label="Nothing"))

# A custom empty label with tuple
field1 = forms.DateField(
    widget=SelectDateWidget(
        empty_label=("Choose Year", "Choose Month", "Choose Day"),
    ),
)
返回顶部