天天看點

django 1.8 官方文檔翻譯:5-2-2 表單素材 ( Media 類)表單素材 ( Media 類)

表單素材 (

Media

類)

渲染有吸引力的、易于使用的web表單不僅僅需要HTML – 同時也需要CSS樣式表,并且,如果你打算使用奇妙的web2.0元件,你也需要在每個頁面包含一些JavaScript。任何提供的頁面都需要CSS和JavaScript的精确配合,它依賴于頁面上所使用的元件。

這就是素材定義所導入的位置。Django允許你将一些不同的檔案 – 像樣式表和腳本 – 與需要這些素材的表單群組件相關聯。例如,如果你想要使用月曆來渲染DateField,你可以定義一個自定義的月曆元件。這個元件可以與渲染月曆所需的CSS和JavaScript關聯。當月曆元件用在表單上的時候,Django可以識别出所需的CSS和JavaScript檔案,并且提供一個檔案名的清單,以便在你的web頁面上簡單地包含這些檔案。

素材和Django Admin

Django的Admin應用為月曆、過濾選擇等一些東西定義了一些自定義的元件。這些元件定義了素材的需求,DJango Admin使用這些自定義元件來代替Django預設的元件。Admin模闆隻包含在提供頁面上渲染元件所需的那些檔案。

如果你喜歡Django Admin應用所使用的那些元件,可以在你的應用中随意使用它們。它們位于

django.contrib.admin.widgets

選擇哪個JavaScript工具包?

現在有許多JavaScript工具包,它們中許多都包含元件(比如月曆元件),可以用于提升你的應用。Django 有意避免去稱贊任何一個JavaScript工具包。每個工具包都有自己的有點和缺點 – 要使用适合你需求的任何一個。Django 有能力內建任何JavaScript工具包。

作為靜态定義的素材

定義素材的最簡單方式是作為靜态定義。如果使用這種方式,定義在

Media

内部類中出現,内部類的屬性定義了需求。

這是一個簡單的例子:

from django import forms

class CalendarWidget(forms.TextInput):
    class Media:
        css = {
            'all': ('pretty.css',)
        }
        js = ('animations.js', 'actions.js')
           

上面的代碼定義了 

CalendarWidget

,它繼承于

TextInput

。每次CalendarWidget在表單上使用時,表單都會包含CSS檔案

pretty.css

,以及JavaScript檔案

animations.js

actions.js

靜态定義在運作時被轉換為名為

media

的元件屬性。

CalendarWidget

執行個體的素材清單可以通過這種方式擷取:

>>> w = CalendarWidget()
>>> print(w.media)
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>
           

下面是所有可能的

Media

選項的清單。它們之中沒有必需選項。

css

各種表單和輸出媒體所需的,描述CSS的字典。

字典中的值應該為檔案名稱的清單或者元組。對于如何指定這些檔案的路徑,詳見

路徑的章節

字典中的鍵位輸出媒體的類型。它們和媒體聲明中CSS檔案接受的類型相同: ‘all’, ‘aural’, ‘braille’, ‘embossed’, ‘handheld’, ‘print’, ‘projection’, ‘screen’, ‘tty’ 和‘tv’。如果你需要為不同的媒體類型使用不同的樣式表,要為每個輸出媒體提供一個CSS檔案的清單。下面的例子提供了兩個CSS選項 – 一個用于螢幕,另一個用于列印:

class Media:
    css = {
        'screen': ('pretty.css',),
        'print': ('newspaper.css',)
    }
           

如果一組CSS檔案适用于多種輸出媒體的類型,字典的鍵可以為輸出媒體類型的逗号分隔的清單。在下面的例子中,TV和投影儀具有相同的媒體需求:

class Media:
    css = {
        'screen': ('pretty.css',),
        'tv,projector': ('lo_res.css',),
        'print': ('newspaper.css',)
    }
           

如果最後的CSS定義即将被渲染,會變成下面的HTML:

<link href="http://static.example.com/pretty.css" type="text/css" media="screen" rel="stylesheet" />
<link href="http://static.example.com/lo_res.css" type="text/css" media="tv,projector" rel="stylesheet" />
<link href="http://static.example.com/newspaper.css" type="text/css" media="print" rel="stylesheet" />
           

js

所需的JavaScript檔案由一個元組來描述。如何制定這些檔案的路徑,詳見

路徑一節

extend

一直布爾值,定義了

Media

聲明的繼承行為。

通常,任何使用靜态

Media

定義的對象都會繼承所有和父元件相關的素材。無論父對象如何定義它自己的需求,都是這樣。例如,如果我們打算從上面的例子中擴充我們的基礎月曆控件:

>>> class FancyCalendarWidget(CalendarWidget):
...     class Media:
...         css = {
...             'all': ('fancy.css',)
...         }
...         js = ('whizbang.js',)

>>> w = FancyCalendarWidget()
>>> print(w.media)
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<link href="http://static.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>
           

 FancyCalendar 元件繼承了所有父元件的素材。如果你不想讓

Media

以這種方式被繼承,要向

Media

聲明中添加

extend=False

聲明:

>>> class FancyCalendarWidget(CalendarWidget):
...     class Media:
...         extend = False
...         css = {
...             'all': ('fancy.css',)
...         }
...         js = ('whizbang.js',)

>>> w = FancyCalendarWidget()
>>> print(w.media)
<link href="http://static.example.com/fancy.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>
           

如果你需要對繼承進行更多控制,要使用

動态屬性

來定義你的素材。動态屬性可以提供更多的控制,來控制繼承哪個檔案。

Media as a dynamic property

如果你需要對素材需求進行更多的複雜操作,你可以直接定義

media

屬性。這可以通過定義一個傳回

forms.Media

執行個體的元件屬性來實作。

forms.Media

的構造器接受

css

js

關鍵字參數,和在靜态媒體定義中的格式相同。

例如,我們的月曆元件的靜态定義可以定義成動态形式:

class CalendarWidget(forms.TextInput):
    def _media(self):
        return forms.Media(css={'all': ('pretty.css',)},
                           js=('animations.js', 'actions.js'))
    media = property(_media)
           

對于如何建構動态

media

屬性的的傳回值,詳見

媒體對象

一節。

素材定義中的路徑

用于指定素材的路徑可以是相對的或者絕對的。如果路徑以

/

http://

或者

https://

開頭,會被解釋為絕對路徑。所有其它的路徑會在開頭追加合适字首的值。

作為 

staticfiles app

的簡介的一部分,添加了兩個新的設定,它們涉及到渲染完整頁面所需的“靜态檔案”:

STATIC_URL

STATIC_ROOT

Django 會檢查是否

STATIC_URL

設定不是

None

,來尋找合适的字首來使用,并且會自動回退使用

MEDIA_URL

。例如,如果你站點的

MEDIA_URL

'http://uploads.example.com/'

并且

STATIC_URL

None

>>> from django import forms
>>> class CalendarWidget(forms.TextInput):
...     class Media:
...         css = {
...             'all': ('/css/pretty.css',),
...         }
...         js = ('animations.js', 'http://othersite.com/actions.js')

>>> w = CalendarWidget()
>>> print(w.media)
<link href="/css/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://uploads.example.com/animations.js"></script>
<script type="text/javascript" src="http://othersite.com/actions.js"></script>
           

但如果

STATIC_URL

'http://static.example.com/'

>>> w = CalendarWidget()
>>> print(w.media)
<link href="/css/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://othersite.com/actions.js"></script>
           

Media

對象

當你通路表單上的一個元件的

media

屬性時,傳回值是一個

forms.Media

對象。就像已經看到的那樣,表示 

Media

對象的字元串,是在你的HTML頁面的

<head>

代碼段包含相關檔案所需的HTML。

然而,

Media

對象具有一些其它的有趣屬性。

素材的子集

如果你僅僅想得到特定類型的檔案,你可以使用下标運算符來過濾出你感興趣的媒體。例如:

>>> w = CalendarWidget()
>>> print(w.media)
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>

>>> print(w.media['css'])
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
           

當你使用下标運算符的時候,傳回值是一個新的 

Media

對象,但是隻含有感興趣的媒體。

組合

Media

Media

對象可以添加到一起。添加兩個

Media

的時候,産生的

Media

對象含有二者指定的素材的并集:

>>> from django import forms
>>> class CalendarWidget(forms.TextInput):
...     class Media:
...         css = {
...             'all': ('pretty.css',)
...         }
...         js = ('animations.js', 'actions.js')

>>> class OtherWidget(forms.TextInput):
...     class Media:
...         js = ('whizbang.js',)

>>> w1 = CalendarWidget()
>>> w2 = OtherWidget()
>>> print(w1.media + w2.media)
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>
           

表單上的

Media

元件并不是唯一擁有

media

定義的對象 – 表單可以定義

media

。在表單上定義

media

的規則群組件上面一樣:定義可以為靜态的或者動态的。聲明的路徑和繼承規則也嚴格一緻。

無論是否你定義了

media

, 所有表單對象都有

media

屬性。這個屬性的預設值是,向所有屬于這個表單的元件添加

media

定義的結果。

>>> from django import forms
>>> class ContactForm(forms.Form):
...     date = DateField(widget=CalendarWidget)
...     name = CharField(max_length=40, widget=OtherWidget)

>>> f = ContactForm()
>>> f.media
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>
           

如果你打算向表單關聯一些額外的素材 – 例如,表單布局的CSS – 隻是向表單添加

Media

聲明就可以了:

>>> class ContactForm(forms.Form):
...     date = DateField(widget=CalendarWidget)
...     name = CharField(max_length=40, widget=OtherWidget)
...
...     class Media:
...         css = {
...             'all': ('layout.css',)
...         }

>>> f = ContactForm()
>>> f.media
<link href="http://static.example.com/pretty.css" type="text/css" media="all" rel="stylesheet" />
<link href="http://static.example.com/layout.css" type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/animations.js"></script>
<script type="text/javascript" src="http://static.example.com/actions.js"></script>
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>
           
譯者: Django 文檔協作翻譯小組 ,原文: Integrating media 本文以 CC BY-NC-SA 3.0 協定釋出,轉載請保留作者署名和文章出處。 人手緊缺,有興趣的朋友可以加入我們,完全公益性質。交流群:467338606。
下一篇: sort初探