# Widgets
Widget 是Django 對HTML 輸入元素的表示。Widget 負責渲染HTML和提取GET/POST 字典中的數據。
小貼士
不要將Widget 與[_表單字段_](fields.html)搞混淆。表單字段負責驗證輸入并直接在模板中使用。Widget 負責渲染網頁上HTML 表單的輸入元素和提取提交的原始數據。但是,Widget 需要[_賦值_](#widget-to-field)給表單的字段。
## 指定Widget
每當你指定表單的一個字段的時候,Django 將使用適合其數據類型的默認Widget。若要查找每個字段使用的Widget,參見[_內建的字段_](fields.html#built-in-fields)文檔。
然而,如果你想要使用一個不同的Widget,你可以在定義字段時使用[`widget`](fields.html#django.forms.Field.widget "django.forms.Field.widget") 參數。例如:
```
from django import forms
class CommentForm(forms.Form):
name = forms.CharField()
url = forms.URLField()
comment = forms.CharField(widget=forms.Textarea)
```
這將使用一個[`Textarea`](#django.forms.Textarea "django.forms.Textarea") Widget來設置表單的評論 ,而不是默認的[`TextInput`](#django.forms.TextInput "django.forms.TextInput") Widget。
## 設置Widget 的參數
很多Widget 都有可選的參數;它們可以在定義字段的Widget 時設置。在下面的示例中,設置了[`SelectDateWidget`](#django.forms.extras.widgets.SelectDateWidget "django.forms.extras.widgets.SelectDateWidget") 的[`years`](#django.forms.extras.widgets.SelectDateWidget.years "django.forms.extras.widgets.SelectDateWidget.years") 屬性:
```
from django import forms
from django.forms.extras.widgets import SelectDateWidget
BIRTH_YEAR_CHOICES = ('1980', '1981', '1982')
FAVORITE_COLORS_CHOICES = (('blue', 'Blue'),
('green', 'Green'),
('black', 'Black'))
class SimpleForm(forms.Form):
birth_year = forms.DateField(widget=SelectDateWidget(years=BIRTH_YEAR_CHOICES))
favorite_colors = forms.MultipleChoiceField(required=False,
widget=forms.CheckboxSelectMultiple, choices=FAVORITE_COLORS_CHOICES)
```
可用的Widget 以及它們接收的參數,參見[_內建的Widget_](#built-in-widgets)。
## 繼承自Select 的Widget
繼承自[`Select`](#django.forms.Select "django.forms.Select") 的Widget 負責處理HTML 選項。它們呈現給用戶一個可以選擇的選項列表。不同的Widget 以不同的方式呈現選項;[`Select`](#django.forms.Select "django.forms.Select") 使用HTML 的列表形式`<select>`,而[`RadioSelect`](#django.forms.RadioSelect "django.forms.RadioSelect") 使用單選按鈕。
[`ChoiceField`](fields.html#django.forms.ChoiceField "django.forms.ChoiceField") 字段默認使用[`Select`](#django.forms.Select "django.forms.Select")。Widget 上顯示的選項來自[`ChoiceField`](fields.html#django.forms.ChoiceField "django.forms.ChoiceField"),對[`ChoiceField.choices`](fields.html#django.forms.ChoiceField.choices "django.forms.ChoiceField.choices") 的改變將更新[`Select.choices`](#django.forms.Select.choices "django.forms.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`](#django.forms.Select.choices "django.forms.Select.choices") 屬性的Widget 也可以用于不是基于選項的字段 , 例如[`CharField`](fields.html#django.forms.CharField "django.forms.CharField") —— 當選項與模型有關而不只是Widget 時,建議使用基于[`ChoiceField`](fields.html#django.forms.ChoiceField "django.forms.ChoiceField") 的字段。
## 自定義Widget 的實例
當Django 渲染Widget 成HTML 時,它只渲染最少的標記 —— Django 不會添加class 的名稱和特定于Widget 的其它屬性。這表示,網頁上所有[`TextInput`](#django.forms.TextInput "django.forms.TextInput") 的外觀是一樣的。
有兩種自定義Widget 的方式:基于每個[_Widget 實例_](#styling-widget-instances)和基于每個[_Widget 類_](#styling-widget-classes)。
### 設置Widget 實例的樣式
如果你想讓某個Widget 實例與其它Widget 看上去不一樣,你需要在Widget 對象實例化并賦值給一個表單字段時指定額外的屬性(以及可能需要在你的CSS 文件中添加一些規則)。
例如下面這個簡單的表單:
```
from django import forms
class CommentForm(forms.Form):
name = forms.CharField()
url = forms.URLField()
comment = forms.CharField()
```
這個表單包含三個默認的[`TextInput`](#django.forms.TextInput "django.forms.TextInput") Widget,以默認的方式渲染 —— 沒有CSS 類、沒有額外的屬性。這表示每個Widget 的輸入框將渲染得一模一樣:
```
>>> f = CommentForm(auto_id=False)
>>> f.as_table()
<tr><th>Name:</th><td><input type="text" name="name" /></td></tr>
<tr><th>Url:</th><td><input type="url" name="url"/></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" /></td></tr>
```
在真正得網頁中,你可能不想讓每個Widget 看上去都一樣。你可能想要給comment 一個更大的輸入元素,你可能想讓‘name’ Widget 具有一些特殊的CSS 類。可以指定‘type’ 屬性來利用新式的HTML5 輸入類型。在創建Widget 時使用[`Widget.attrs`](#django.forms.Widget.attrs "django.forms.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'}))
```
Django 將在渲染的輸出中包含額外的屬性:
```
>>> f = CommentForm(auto_id=False)
>>> f.as_table()
<tr><th>Name:</th><td><input type="text" name="name" class="special"/></td></tr>
<tr><th>Url:</th><td><input type="url" name="url"/></td></tr>
<tr><th>Comment:</th><td><input type="text" name="comment" size="40"/></td></tr>
```
你還可以使用[`attrs`](#django.forms.Widget.attrs "django.forms.Widget.attrs") 設置HTML `id`。參見[`BoundField.id_for_label`](api.html#django.forms.BoundField.id_for_label "django.forms.BoundField.id_for_label") 示例。
### 設置Widget 類的樣式
可以添加(`css` 和`javascript`)給Widget,以及深度定制它們的外觀和行為。
概況來講,你需要子類化Widget 并[_定義一個“Media” 內聯類_](../../topics/forms/media.html#assets-as-a-static-definition) 或 [_創建一個“media” 屬性_](../../topics/forms/media.html#dynamic-property)。
這些方法涉及到Python 高級編程,詳細細節在[_表單Assets_](../../topics/forms/media.html) 主題中講述。
## Widget 的基類
[`Widget`](#django.forms.Widget "django.forms.Widget") 和[`MultiWidget`](#django.forms.MultiWidget "django.forms.MultiWidget") 是所有[_內建Widget_](#built-in-widgets) 的基類,并可用于自定義Widget 的基類。
_class _`Widget`(_attrs=None_)
這是個抽象類,它不可以渲染,但是提供基本的屬性[`attrs`](#django.forms.Widget.attrs "django.forms.Widget.attrs")。你可以在自定義的Widget 中實現或覆蓋[`render()`](#django.forms.Widget.render "django.forms.Widget.render") 方法。
`attrs`
包含渲染后的Widget 將要設置的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" />'
```
Changed in Django 1.8:
如果你給一個屬性賦值`True` 或`False`,它將渲染成一個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" />'
```
`render`(_name_, _value_, _attrs=None_)
返回Widget 的HTML,為一個Unicode 字符串。子類必須實現這個方法,否則將引發`NotImplementedError`。
它不會確保給出的‘value’ 是一個合法的輸入,因此子類的實現應該防衛式地編程。
`value_from_datadict`(_data_, _files_, _name_)
根據一個字典和該Widget 的名稱,返回該Widget 的值。`files` may contain data coming from [`request.`](../request-response.html#django.http.HttpRequest.FILES "django.http.HttpRequest.FILES")FILES. 如果沒有提供value,則返回`None`。 在處理表單數據的過程中,`value_from_datadict` 可能調用多次,所以如果你自定義并添加額外的耗時處理時,你應該自己實現一些緩存機制。
_class _`MultiWidget`(_widgets_, _attrs=None_)
由多個Widget 組合而成的Widget。[`MultiWidget`](#django.forms.MultiWidget "django.forms.MultiWidget") 始終與[`MultiValueField`](fields.html#django.forms.MultiValueField "django.forms.MultiValueField") 聯合使用。
[`MultiWidget`](#django.forms.MultiWidget "django.forms.MultiWidget") 具有一個必選參數:
`widgets`
一個包含需要的Widget 的可迭代對象。
以及一個必需的方法:
`decompress`(_value_)
這個方法接受來自字段的一個“壓縮”的值,并返回“解壓”的值的一個列表。可以假設輸入的值是合法的,但不一定是非空的。
子類**必須實現** 這個方法,而且因為值可能為空,實現必須要防衛這點。
“解壓”的基本原理是需要“分離”組合的表單字段的值為每個Widget 的值。
有個例子是,[`SplitDateTimeWidget`](#django.forms.SplitDateTimeWidget "django.forms.SplitDateTimeWidget") 將[`datetime`](https://docs.python.org/3/library/datetime.html#datetime.datetime "(in Python v3.4)") 值分離成兩個獨立的值分別表示日期和時間:
```
from django.forms import MultiWidget
class SplitDateTimeWidget(MultiWidget):
# ...
def decompress(self, value):
if value:
return [value.date(), value.time().replace(microsecond=0)]
return [None, None]
```
小貼士
注意,[`MultiValueField`](fields.html#django.forms.MultiValueField "django.forms.MultiValueField") 有一個[`compress()`](fields.html#django.forms.MultiValueField.compress "django.forms.MultiValueField.compress") 方法用于相反的工作 —— 將所有字段的值組合成一個值。
其它可能需要覆蓋的方法:
`render`(_name_, _value_, _attrs=None_)
這個方法中的 `value`參數的處理方式與[`Widget`](#django.forms.Widget "django.forms.Widget")子類不同,因為需要弄清楚如何為了在不同widget中展示分割單一值。
渲染中使用的`value`參數可以是二者之一:
* 一個`列表`。
* 一個單一值(比如字符串),它是`列表`的“壓縮”表現形式。
如果`value`是個列表,[`render()`](#django.forms.MultiWidget.render "django.forms.MultiWidget.render")的輸出會是一系列渲染后的子widget。如果`value`不是一個列表,首先會通過[`decompress()`](#django.forms.MultiWidget.decompress "django.forms.MultiWidget.decompress")方法來預處理,創建列表,之后再渲染。
`render()`方法執行HTML渲染時,列表中的每個值都使用相應的widget來渲染 -- 第一個值在第一個widget中渲染,第二個值在第二個widget中渲染,以此類推。
不像單一值的widget,[`render()`](#django.forms.MultiWidget.render "django.forms.MultiWidget.render") 方法并不需要在子類中實現。
`format_output`(_rendered_widgets_)
接受選然后的widget(以字符串形式)的一個列表,返回表示全部HTML的Unicode字符串。
這個鉤子允許你以任何你想要的方式,格式化widget的HTML設計。
下面示例中的Widget 繼承[`MultiWidget`](#django.forms.MultiWidget "django.forms.MultiWidget") 以在不同的選擇框中顯示年、月、日。這個Widget 主要想用于[`DateField`](fields.html#django.forms.DateField "django.forms.DateField") 而不是[`MultiValueField`](fields.html#django.forms.MultiValueField "django.forms.MultiValueField"),所以我們實現了[`value_from_datadict()`](#django.forms.Widget.value_from_datadict "django.forms.Widget.value_from_datadict"):
```
from datetime import date
from django.forms import widgets
class DateSelectorWidget(widgets.MultiWidget):
def __init__(self, attrs=None):
# create choices for days, months, years
# example below, the rest snipped for brevity.
years = [(year, year) for year in (2011, 2012, 2013)]
_widgets = (
widgets.Select(attrs=attrs, choices=days),
widgets.Select(attrs=attrs, choices=months),
widgets.Select(attrs=attrs, choices=years),
)
super(DateSelectorWidget, self).__init__(_widgets, attrs)
def decompress(self, value):
if value:
return [value.day, value.month, value.year]
return [None, None, None]
def format_output(self, rendered_widgets):
return ''.join(rendered_widgets)
def value_from_datadict(self, data, files, name):
datelist = [
widget.value_from_datadict(data, files, name + '_%s' % i)
for i, widget in enumerate(self.widgets)]
try:
D = date(day=int(datelist[0]), month=int(datelist[1]),
year=int(datelist[2]))
except ValueError:
return ''
else:
return str(D)
```
構造器在一個元組中創建了多個[`Select`](#django.forms.Select "django.forms.Select") widget。`超`類使用這個元組來啟動widget。
[`format_output()`](#django.forms.MultiWidget.format_output "django.forms.MultiWidget.format_output")方法相當于在這里沒有干什么新的事情(實際上,它和`MultiWidget`中默認實現的東西相同),但是這個想法是,你可以以自己的方式在widget之間添加自定義的HTML。
必需的[`decompress()`](#django.forms.MultiWidget.decompress "django.forms.MultiWidget.decompress")方法將`datetime.date` 值拆成年、月和日的值,對應每個widget。注意這個方法如何處理`value`為`None`的情況。
[`value_from_datadict()`](#django.forms.Widget.value_from_datadict "django.forms.Widget.value_from_datadict")的默認實現會返回一個列表,對應每一個`Widget`。當和[`MultiValueField`](fields.html#django.forms.MultiValueField "django.forms.MultiValueField")一起使用`MultiWidget`的時候,這樣會非常合理,但是由于我們想要和擁有單一值得[`DateField`](fields.html#django.forms.DateField "django.forms.DateField")一起使用這個widget,我們必須覆寫這一方法,將所有子widget的數據組裝成`datetime.date`。這個方法從`POST` 字典中獲取數據,并且構造和驗證日期。如果日期有效,會返回它的字符串,否則會返回一個空字符串,它會使`form.is_valid`返回`False`。
## 內建的Widget
Django 提供所有基本的HTML Widget,并在`django.forms.widgets` 模塊中提供一些常見的Widget 組,包括[_文本的輸入_](#text-widgets)、[_各種選擇框_](#selector-widgets)、[_文件上傳_](#file-upload-widgets)和[_多值輸入_](#composite-widgets)。
### 處理文本輸入的Widget
這些Widget 使用HTML 元素`input` 和 `textarea`。
#### TextInput
_class _`TextInput`
文本輸入:`<input type="text" ...>`
#### NumberInput
_class _`NumberInput`
文本輸入:`<input type="number" ...>`
注意,不是所有瀏覽器的`number`輸入類型都支持輸入本地化的數字。Django 將字段的[`localize`](fields.html#django.forms.Field.localize "django.forms.Field.localize") 屬性設置為`True` 以避免字段使用它們。
#### EmailInput
_class _`EmailInput`
文本輸入:`<input type="email" ...>`
#### URLInput
_class _`URLInput`
文本輸入:`<input type="url" ...>`
#### PasswordInput
_class _`PasswordInput`
密碼輸入:`<input type='password' ...>`
接收一個可選的參數:
`render_value`
決定在驗證錯誤后重新顯示表單時,Widget 是否填充(默認為`False`)。
#### HiddenInput
_class _`HiddenInput`
隱藏的輸入:`<input type='hidden' ...>`
注意,還有一個[`MultipleHiddenInput`](#django.forms.MultipleHiddenInput "django.forms.MultipleHiddenInput") Widget,它封裝一組隱藏的輸入元素。
#### DateInput
_class _`DateInput`
日期以普通的文本框輸入:`<input type='text' ...>`
接收的參數與[`TextInput`](#django.forms.TextInput "django.forms.TextInput") 相同,但是帶有一些可選的參數:
`format`
字段的初始值應該顯示的格式。
如果沒有提供`format` 參數,默認的格式為參考[_本地化格式_](../../topics/i18n/formatting.html#format-localization)在[`DATE_INPUT_FORMATS`](../settings.html#std:setting-DATE_INPUT_FORMATS) 中找到的第一個格式。
#### DateTimeInput
_class _`DateTimeInput`
日期/時間以普通的文本框輸入:`<input type='text' ...>`
接收的參數與[`TextInput`](#django.forms.TextInput "django.forms.TextInput") 相同,但是帶有一些可選的參數:
`format`
字段的初始值應該顯示的格式。
如果沒有提供`format` 參數,默認的格式為參考[_本地化格式_](../../topics/i18n/formatting.html#format-localization)在[`DATETIME_INPUT_FORMATS`](../settings.html#std:setting-DATETIME_INPUT_FORMATS) 中找到的第一個格式。
#### TimeInput
_class _`TimeInput`
時間以普通的文本框輸入:`<input type='text' ...>`
接收的參數與[`TextInput`](#django.forms.TextInput "django.forms.TextInput") 相同,但是帶有一些可選的參數:
`format`
字段的初始值應該顯示的格式。
如果沒有提供`format` 參數,默認的格式為參考[_本地化格式_](../../topics/i18n/formatting.html#format-localization)在[`TIME_INPUT_FORMATS`](../settings.html#std:setting-TIME_INPUT_FORMATS) 中找到的第一個格式。
#### Textarea
_class _`Textarea`
文本區域:`<textarea>...</textarea>`
### 選擇和復選框Widget
#### CheckboxInput
_class _`CheckboxInput`
復選框:`<input type='checkbox' ...>`
接受一個可選的參數:
`check_test`
一個可調用的對象,接收`CheckboxInput` 的值并如果復選框應該勾上返回`True`。
#### Select
_class _`Select`
Select widget:`<select><option ...>...</select>`
`choices`
當表單字段沒有`choices` 屬性時,該屬性是隨意的。如果字段有choice 屬性,當[`字段`](fields.html#django.forms.Field "django.forms.Field")的該屬性更新時,它將覆蓋你在這里的任何設置。
#### NullBooleanSelect
_class _`NullBooleanSelect`
Select Widget,選項為‘Unknown’、‘Yes’ 和‘No’。
#### SelectMultiple
_class _`SelectMultiple`
類似[`Select`](#django.forms.Select "django.forms.Select"),但是允許多個選擇:`<select multiple='multiple'>...</select>`
#### RadioSelect
_class _`RadioSelect`
類似[`Select`](#django.forms.Select "django.forms.Select"),但是渲染成`<li>` 標簽中的一個單選按鈕列表:
```
<ul>
<li><input type='radio' name='...'></li>
...
</ul>
```
你可以迭代模板中的單選按鈕來更細致地控制生成的HTML。假設表單`myform` 具有一個字段`beatles`,它使用`RadioSelect` 作為Widget:
```
{% for radio in myform.beatles %}
<div class="myradio">
{{ radio }}
</div>
{% endfor %}
```
它將生成以下HTML:
```
<div class="myradio">
<label for="id_beatles_0"><input id="id_beatles_0" name="beatles" type="radio" value="john" /> John</label>
</div>
<div class="myradio">
<label for="id_beatles_1"><input id="id_beatles_1" name="beatles" type="radio" value="paul" /> Paul</label>
</div>
<div class="myradio">
<label for="id_beatles_2"><input id="id_beatles_2" name="beatles" type="radio" value="george" /> George</label>
</div>
<div class="myradio">
<label for="id_beatles_3"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" /> Ringo</label>
</div>
```
這包括`<label>` 標簽。你可以使用單選按鈕的`tag`、`choice_label` 和 `id_for_label` 屬性進行更細的控制。例如,這個模板:
```
{% for radio in myform.beatles %}
<label for="{{ radio.id_for_label }}">
{{ radio.choice_label }}
<span class="radio">{{ radio.tag }}</span>
</label>
{% endfor %}
```
... 將生成下面的HTML:
```
<label for="id_beatles_0">
John
<span class="radio"><input id="id_beatles_0" name="beatles" type="radio" value="john" /></span>
</label>
<label for="id_beatles_1">
Paul
<span class="radio"><input id="id_beatles_1" name="beatles" type="radio" value="paul" /></span>
</label>
<label for="id_beatles_2">
George
<span class="radio"><input id="id_beatles_2" name="beatles" type="radio" value="george" /></span>
</label>
<label for="id_beatles_3">
Ringo
<span class="radio"><input id="id_beatles_3" name="beatles" type="radio" value="ringo" /></span>
</label>
```
如果你不迭代單選按鈕 —— 例如,你的模板只是簡單地包含`{{ myform.beatles }}` —— 它們將以`<ul>` 中的`<li>` 標簽輸出,就像上面一樣。
外層的`<ul>` 將帶有定義在Widget 上的`id` 屬性。
Changed in Django 1.7:
當迭代單選按鈕時,`label` 和`input` 標簽分別包含`for` 和`id` 屬性。每個單項按鈕具有一個`id_for_label` 屬性來輸出元素的ID。
#### CheckboxSelectMultiple
_class _`CheckboxSelectMultiple`
類似[`SelectMultiple`](#django.forms.SelectMultiple "django.forms.SelectMultiple"),但是渲染成一個復選框列表:
```
<ul>
<li><input type='checkbox' name='...' ></li>
...
</ul>
```
外層的`<ul>` 具有定義在Widget 上的`id` 屬性。
類似[`RadioSelect`](#django.forms.RadioSelect "django.forms.RadioSelect"),你可以迭代列表的每個復選框。更多細節參見[`RadioSelect`](#django.forms.RadioSelect "django.forms.RadioSelect") 的文檔。
Changed in Django 1.7:
當迭代單選按鈕時,`label` 和`input` 標簽分別包含`for` 和`id` 屬性。 每個單項按鈕具有一個`id_for_label` 屬性來輸出元素的ID。
### 文件上傳Widget
#### FileInput
_class _`FileInput`
文件上傳輸入:`<input type='file' ...>`
#### ClearableFileInput
_class _`ClearableFileInput`
文件上傳輸入:`<input type='file' ...>`,帶有一個額外的復選框,如果該字段不是必選的且有初始的數據,可以清除字段的值。
### 復合Widget
#### MultipleHiddenInput
_class _`MultipleHiddenInput`
多個`<input type='hidden' ...>` Widget。
一個處理多個隱藏的Widget 的Widget,用于值為一個列表的字段。
`choices`
當表單字段沒有`choices` 屬性時,這個屬性是可選的。如果字段有choice 屬性,當[`字段`](fields.html#django.forms.Field "django.forms.Field")的該屬性更新時,它將覆蓋你在這里的任何設置。
#### SplitDateTimeWidget
_class _`SplitDateTimeWidget`
封裝(使用[`MultiWidget`](#django.forms.MultiWidget "django.forms.MultiWidget"))兩個Widget:[`DateInput`](#django.forms.DateInput "django.forms.DateInput") 用于日期,[`TimeInput`](#django.forms.TimeInput "django.forms.TimeInput") 用于時間。
`SplitDateTimeWidget` 有兩個可選的屬性:
`date_format`
類似[`DateInput.format`](#django.forms.DateInput.format "django.forms.DateInput.format")
`time_format`
類似[`TimeInput.format`](#django.forms.TimeInput.format "django.forms.TimeInput.format")
#### SplitHiddenDateTimeWidget
_class _`SplitHiddenDateTimeWidget`
類似[`SplitDateTimeWidget`](#django.forms.SplitDateTimeWidget "django.forms.SplitDateTimeWidget"),但是日期和時間都使用[`HiddenInput`](#django.forms.HiddenInput "django.forms.HiddenInput")。
#### SelectDateWidget
_class _`SelectDateWidget`[[source]](../../_modules/django/forms/extras/widgets.html#SelectDateWidget)
封裝三個[`Select`](#django.forms.Select "django.forms.Select") Widget:分別用于年、月、日。注意,這個Widget 與標準的Widget 位于不同的文件中。
接收一個可選的參數:
`years`
一個可選的列表/元組,用于”年“選擇框。默認為包含當前年份和未來9年的一個列表。
`months`
New in Django 1.7\.
一個可選的字典,用于”月“選擇框。
字典的鍵對應于月份的數字(從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`
New in Django 1.8\.
如果[`DateField`](fields.html#django.forms.DateField "django.forms.DateField") 不是必選的,[`SelectDateWidget`](#django.forms.extras.widgets.SelectDateWidget "django.forms.extras.widgets.SelectDateWidget") 將有一個空的選項位于選項的頂部(默認為`---`)。你可以通過`empty_label` 屬性修改這個文本。`empty_label` 可以是一個`字符串`、`列表` 或`元組`。當使用字符串時,所有的選擇框都帶有這個空選項。如果`empty_label` 為具有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"))
```
> 譯者:[Django 文檔協作翻譯小組](http://python.usyiyi.cn/django/index.html),原文:[Built-in widgets](https://docs.djangoproject.com/en/1.8/ref/forms/widgets/)。
>
> 本文以 [CC BY-NC-SA 3.0](http://creativecommons.org/licenses/by-nc-sa/3.0/cn/) 協議發布,轉載請保留作者署名和文章出處。
>
> [Django 文檔協作翻譯小組](http://python.usyiyi.cn/django/index.html)人手緊缺,有興趣的朋友可以加入我們,完全公益性質。交流群:467338606。
- 新手入門
- 從零開始
- 概覽
- 安裝
- 教程
- 第1部分:模型
- 第2部分:管理站點
- 第3部分:視圖和模板
- 第4部分:表單和通用視圖
- 第5部分:測試
- 第6部分:靜態文件
- 高級教程
- 如何編寫可重用的應用
- 為Django編寫首個補丁
- 模型層
- 模型
- 模型語法
- 元選項
- 模型類
- 查詢集
- 執行查詢
- 查找表達式
- 模型的實例
- 實例方法
- 訪問關聯對象
- 遷移
- 模式編輯器
- 編寫遷移
- 高級
- 管理器
- 原始的SQL查詢
- 聚合
- 多數據庫
- 自定義查找
- 條件表達式
- 數據庫函數
- 其它
- 遺留的數據庫
- 提供初始數據
- 優化數據庫訪問
- 視圖層
- 基礎
- URL配置
- 視圖函數
- 快捷函數
- 裝飾器
- 參考
- 內建的視圖
- TemplateResponse 對象
- 文件上傳
- 概覽
- File 對象
- 儲存API
- 管理文件
- 自定義存儲
- 基于類的視圖
- 概覽
- 內建顯示視圖
- 內建編輯視圖
- API參考
- 分類索引
- 高級
- 生成 CSV
- 生成 PDF
- 中間件
- 概覽
- 內建的中間件類
- 模板層
- 基礎
- 面向設計師
- 語言概覽
- 人性化
- 面向程序員
- 表單
- 基礎
- 概覽
- 表單API
- 內建的Widget
- 高級
- 整合媒體
- 開發過程
- 設置
- 概覽
- 應用程序
- 異常
- 概覽
- django-admin 和 manage.py
- 添加自定義的命令
- 測試
- 介紹
- 部署
- 概述
- WSGI服務器
- 部署靜態文件
- 通過email追蹤代碼錯誤
- Admin
- 管理操作
- 管理文檔生成器
- 安全
- 安全概述
- 說明Django中的安全問題
- 點擊劫持保護
- 加密簽名
- 國際化和本地化
- 概述
- 本地化WEB UI格式化輸入
- “本地特色”
- 常見的網站應用工具
- 認證
- 概覽
- 使用認證系統
- 密碼管理
- 日志
- 分頁
- 會話
- 數據驗證
- 其它核心功能
- 按需內容處理
- 重定向
- 信號
- 系統檢查框架