django 1.8 官方文檔翻譯:5-1-4 內建的Widget

Widgets

Widget 是Django 對HTML 輸入元素的表示。Widget 負責渲染HTML和提取GET/POST 字典中的數據。javascript

小貼士css

不要將Widget 與_表單字段_搞混淆。表單字段負責驗證輸入並直接在模板中使用。Widget 負責渲染網頁上HTML 表單的輸入元素和提取提交的原始數據。可是,Widget 須要_賦值_給表單的字段。java

指定Widget

每當你指定表單的一個字段的時候,Django 將使用適合其數據類型的默認Widget。若要查找每一個字段使用的Widget,參見_內建的字段_文檔。django

然而,若是你想要使用一個不一樣的Widget,你能夠在定義字段時使用widget 參數。例如:編程

from django import forms

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

這將使用一個Textarea Widget來設置表單的評論 ,而不是默認的TextInput Widget。緩存

設置Widget 的參數

不少Widget 都有可選的參數;它們能夠在定義字段的Widget 時設置。在下面的示例中,設置了SelectDateWidgetyears 屬性:ui

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_url

繼承自Select 的Widget

繼承自Select 的Widget 負責處理HTML 選項。它們呈現給用戶一個能夠選擇的選項列表。不一樣的Widget 以不一樣的方式呈現選項;Select 使用HTML 的列表形式<select>,而RadioSelect 使用單選按鈕。code

ChoiceField 字段默認使用Select。Widget 上顯示的選項來自ChoiceField,對ChoiceField.choices 的改變將更新Select.choices。例如:orm

>>> 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 屬性的Widget 也能夠用於不是基於選項的字段 , 例如CharField —— 當選項與模型有關而不僅是Widget 時,建議使用基於ChoiceField 的字段。

自定義Widget 的實例

當Django 渲染Widget 成HTML 時,它只渲染最少的標記 —— Django 不會添加class 的名稱和特定於Widget 的其它屬性。這表示,網頁上全部TextInput 的外觀是同樣的。

有兩種自定義Widget 的方式:基於每一個_Widget 實例_和基於每一個_Widget 類_

設置Widget 實例的樣式

若是你想讓某個Widget 實例與其它Widget 看上去不同,你須要在Widget 對象實例化並賦值給一個表單字段時指定額外的屬性(以及可能須要在你的CSS 文件中添加一些規則)。

例以下面這個簡單的表單:

from django import forms

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

這個表單包含三個默認的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 參數能夠實現:

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 設置HTML id。參見BoundField.id_for_label 示例。

設置Widget 類的樣式

能夠添加(cssjavascript)給Widget,以及深度定製它們的外觀和行爲。

概況來說,你須要子類化Widget 並_定義一個「Media」 內聯類__建立一個「media」 屬性_

這些方法涉及到Python 高級編程,詳細細節在_表單Assets_ 主題中講述。

Widget 的基類

WidgetMultiWidget 是全部_內建Widget_ 的基類,並可用於自定義Widget 的基類。

_class _Widget(_attrs=None_)

這是個抽象類,它不能夠渲染,可是提供基本的屬性attrs。你能夠在自定義的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:

若是你給一個屬性賦值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" />'

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.FILES. 若是沒有提供value,則返回None。 在處理表單數據的過程當中,value_from_datadict 可能調用屢次,因此若是你自定義並添加額外的耗時處理時,你應該本身實現一些緩存機制。

_class _MultiWidget(_widgets_, _attrs=None_)

由多個Widget 組合而成的Widget。MultiWidget 始終與MultiValueField 聯合使用。

MultiWidget 具備一個必選參數:

widgets

一個包含須要的Widget 的可迭代對象。

以及一個必需的方法:

decompress(_value_)

這個方法接受來自字段的一個「壓縮」的值,並返回「解壓」的值的一個列表。能夠假設輸入的值是合法的,但不必定是非空的。

子類必須實現 這個方法,並且由於值可能爲空,實現必需要防衛這點。

「解壓」的基本原理是須要「分離」組合的表單字段的值爲每一個Widget 的值。

有個例子是,SplitDateTimeWidget

相關文章
相關標籤/搜索