小部件

小部件是Django对HTML输入元素的表示。该小部件处理HTML的呈现,以及从对应于该小部件的get/post字典中提取数据。

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

小技巧

小部件不应与 form fields . 表单域处理输入验证的逻辑,并直接在模板中使用。小部件处理网页上HTML表单输入元素的呈现和原始提交数据的提取。但是,小部件确实需要 assigned 形成字段。

指定小部件

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

但是,如果要为字段使用不同的小部件,可以使用 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 Widget将以相同的方式出现在您的网页上。

自定义小工具有两种方法: per widget instanceper widget class .

样式小部件实例

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

例如,采取以下形式:

from django import forms


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

此表单将包括三个默认设置 TextInput Widget,默认呈现--没有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>

在真正的Web页面上,您可能不希望每个小部件看起来都一样。您可能希望为评论添加更大的输入元素,并且可能希望‘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>

也可以设置HTML id 使用 attrs . 见 BoundField.id_for_label 举个例子。

样式小部件类

使用小部件,可以添加资产 (cssjavascript )更深入地定制他们的外表和行为。

简言之,您将需要子类化该小部件,并且 define a "Media" inner classcreate a "media" property .

这些方法涉及一些高级的Python编程,并在 Form Assets 主题指南。

基本控件类

基本控件类 WidgetMultiWidget 是所有 built-in widgets 并且可以作为自定义小部件的基础。

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_)[源代码]

返回此小工具的HTMLID属性,以供 <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 字典和这个小部件的名称,返回小部件是否有数据或文件。

方法的结果会影响模型表单中的字段 falls back to its default .

特殊情况是 CheckboxInputCheckboxSelectMultipleSelectMultiple ,它总是返回 False 因为一个未选中的复选框和未选中的 <select multiple> 不要出现在HTML表单提交的数据中,因此用户是否提交了值是未知的。

use_fieldset

用于标识是否应将小部件分组到 <fieldset> 使用一个 <legend> 渲染时。默认为 False 但现在是 True 当小部件包含多个 <input> 标签,如 CheckboxSelectMultipleRadioSelectMultiWidgetSplitDateTimeWidget ,以及 SelectDateWidget

use_required_attribute(initial)[源代码]

给定表单域的 initial 值,返回是否可以使用 required HTML属性。窗体与此方法一起使用 Field.requiredForm.use_required_attribute 确定是否显示 required 每个字段的属性。

默认情况下,返回 False 对于隐藏的小工具和 True 否则。特殊情况是 FileInputClearableFileInput ,返回 False 什么时候? initial 被设置为 CheckboxSelectMultiple ,它总是返回 False 因为浏览器验证需要选中所有复选框,而不是至少选中一个。

在与浏览器验证不兼容的自定义小部件中重写此方法。例如,一个由隐藏的 textarea 元素可能希望始终返回 False 以避免对隐藏字段进行浏览器验证。

MultiWidget

class MultiWidget(widgets, attrs=None)[源代码]

由多个小部件组成的小部件。 MultiWidget 与…携手合作 MultiValueField .

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)[源代码]

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

这种方法 必须执行 通过子类,由于值可能为空,因此实现必须是防御性的。

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

一个例子就是 SplitDateTimeWidget 转A 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' 中介绍的关键字 Widget.get_context()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 . 当使用 MultiWidget 用一个 MultiValueField . 但是因为我们想使用这个小部件 DateField ,我们已重写此方法。这里的实现将子部件中的数据组合成一个字符串,格式如下 DateField 期望。

内置小工具

Django提供了所有基本HTML小部件的表示,以及 django.forms.widgets 模块,包括 the input of textvarious checkboxes and selectorsuploading fileshandling of multi-valued input .

处理文本输入的小部件

这些小部件使用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 渲染 <option> 对于一个 <select> .

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 用一块地 beatles 使用A RadioSelect 作为它的小部件:

<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 分别是小部件。如果没有设置这些属性, 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

“月份”选择框中要使用的月份的可选dict。

dict的键对应于月份号(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 是一个 listtuple 在3个字符串元素中,选择框将有自己的自定义标签。标签应按此顺序排列 ('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"),
    ),
)