鍍金池/ 教程/ Python/ 表單素材 ( <code>Media</code> 類)
點(diǎn)擊劫持保護(hù)
安全問題歸檔
Model 類參考
將遺留數(shù)據(jù)庫整合到Django
關(guān)聯(lián)對象參考
內(nèi)建基于類的視圖的API
聚合
Django 中的用戶認(rèn)證
django.contrib.humanize
Django管理文檔生成器
分頁
使用Django輸出CSV
加密簽名
文件儲存API
安全
Django中的測試
國際化和本地化
為Django編寫首個補(bǔ)丁
條件表達(dá)式
日志
模型元選項
部署靜態(tài)文件
執(zhí)行查詢
使用Django認(rèn)證系統(tǒng)
基于類的視圖
中間件
編寫自定義的django-admin命令
Django 的設(shè)置
格式本地化
數(shù)據(jù)庫訪問優(yōu)化
錯誤報告
基于類的內(nèi)建通用視圖
編寫自定義存儲系統(tǒng)
編寫你的第一個 Django 程序 第3部分
編寫數(shù)據(jù)庫遷移
使用表單
編寫你的第一個 Django 程序 第2部分
編寫你的第一個 Django 程序 第1部分
如何使用會話
系統(tǒng)檢查框架
新手入門
信號
編寫視圖
如何使用WSGI 部署
編寫你的第一個Django應(yīng)用,第6部分
常見的網(wǎng)站應(yīng)用工具
Widgets
內(nèi)建的視圖
模型實例參考
視圖層
Django中的密碼管理
高級教程:如何編寫可重用的應(yīng)用
國際化和本地化
&quot;本地特色&quot;附加功能
TemplateResponse 和 SimpleTemplateResponse
模式編輯器
文件上傳
快速安裝指南
部署 Django
表單 API
表單素材 ( <code>Media</code> 類)
管理文件
其它核心功能
查找 API 參考
表單
Admin
數(shù)據(jù)庫函數(shù)
自定義查找
使用基于類的視圖處理表單
管理操作
開發(fā)過程
編寫你的第一個Django應(yīng)用,第5部分
進(jìn)行原始的sql查詢
模型層
多數(shù)據(jù)庫
編寫你的第一個 Django 程序 第4部分
Django安全
Django 初探
Django異常
重定向應(yīng)用
按需內(nèi)容處理
管理器
視圖裝飾器
驗證器
使用Django輸出PDF
File對象
Django 的快捷函數(shù)
基于類的通用視圖 —— 索引
為模型提供初始數(shù)據(jù)
模板層
URL調(diào)度器
中間件
模型

表單素材 ( <code>Media</code> 類)

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

這就是素材定義所導(dǎo)入的位置。Django允許你將一些不同的文件 -- 像樣式表和腳本 -- 與需要這些素材的表單和組件相關(guān)聯(lián)。例如,如果你想要使用日歷來渲染DateField,你可以定義一個自定義的日歷組件。這個組件可以與渲染日歷所需的CSS和JavaScript關(guān)聯(lián)。當(dāng)日歷組件用在表單上的時候,Django可以識別出所需的CSS和JavaScript文件,并且提供一個文件名的列表,以便在你的web頁面上簡單地包含這些文件。

素材和Django Admin

Django的Admin應(yīng)用為日歷、過濾選擇等一些東西定義了一些自定義的組件。這些組件定義了素材的需求,DJango Admin使用這些自定義組件來代替Django默認(rèn)的組件。Admin模板只包含在提供頁面上渲染組件所需的那些文件。

如果你喜歡Django Admin應(yīng)用所使用的那些組件,可以在你的應(yīng)用中隨意使用它們。它們位于django.contrib.admin.widgets

選擇哪個JavaScript工具包?

現(xiàn)在有許多JavaScript工具包,它們中許多都包含組件(比如日歷組件),可以用于提升你的應(yīng)用。Django 有意避免去稱贊任何一個JavaScript工具包。每個工具包都有自己的有點(diǎn)和缺點(diǎn) -- 要使用適合你需求的任何一個。Django 有能力集成任何JavaScript工具包。

作為靜態(tài)定義的素材

定義素材的最簡單方式是作為靜態(tài)定義。如果使用這種方式,定義在Media內(nèi)部類中出現(xiàn),內(nèi)部類的屬性定義了需求。

這是一個簡單的例子:

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.jsactions.js。

靜態(tài)定義在運(yùn)行時被轉(zhuǎn)換為名為media的組件屬性。CalendarWidget實例的素材列表可以通過這種方式獲?。?/p>

>>> w = CalendarWidget()
>>> print(w.media)
<link  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的字典。

字典中的值應(yīng)該為文件名稱的列表或者元組。對于如何指定這些文件的路徑,詳見路徑的章節(jié)

字典中的鍵位輸出媒體的類型。它們和媒體聲明中CSS文件接受的類型相同: ‘a(chǎn)ll’, ‘a(chǎn)ural’, ‘braille’, ‘embossed’, ‘handheld’, ‘print’, ‘projection’, ‘screen’, ‘tty’ 和‘tv’。如果你需要為不同的媒體類型使用不同的樣式表,要為每個輸出媒體提供一個CSS文件的列表。下面的例子提供了兩個CSS選項 -- 一個用于屏幕,另一個用于打?。?/p>

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  type="text/css" media="screen" rel="stylesheet" />
<link  type="text/css" media="tv,projector" rel="stylesheet" />
<link  type="text/css" media="print" rel="stylesheet" />

js

所需的JavaScript文件由一個元組來描述。如何制定這些文件的路徑,詳見路徑一節(jié)

extend

一直布爾值,定義了Media聲明的繼承行為。

通常,任何使用靜態(tài)Media定義的對象都會繼承所有和父組件相關(guān)的素材。無論父對象如何定義它自己的需求,都是這樣。例如,如果我們打算從上面的例子中擴(kuò)展我們的基礎(chǔ)日歷控件:

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

>>> w = FancyCalendarWidget()
>>> print(w.media)
<link  type="text/css" media="all" rel="stylesheet" />
<link  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  type="text/css" media="all" rel="stylesheet" />
<script type="text/javascript" src="http://static.example.com/whizbang.js"></script>

如果你需要對繼承進(jìn)行更多控制,要使用動態(tài)屬性來定義你的素材。動態(tài)屬性可以提供更多的控制,來控制繼承哪個文件。

Media as a dynamic property

如果你需要對素材需求進(jìn)行更多的復(fù)雜操作,你可以直接定義media屬性。這可以通過定義一個返回forms.Media實例的組件屬性來實現(xiàn)。forms.Media的構(gòu)造器接受 cssjs關(guān)鍵字參數(shù),和在靜態(tài)媒體定義中的格式相同。

例如,我們的日歷組件的靜態(tài)定義可以定義成動態(tài)形式:

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

對于如何構(gòu)建動態(tài)media 屬性的的返回值,詳見媒體對象一節(jié)。

素材定義中的路徑

用于指定素材的路徑可以是相對的或者絕對的。如果路徑以 /,http:// 或者https://開頭,會被解釋為絕對路徑。所有其它的路徑會在開頭追加合適前綴的值。

作為 staticfiles app的簡介的一部分,添加了兩個新的設(shè)置,它們涉及到渲染完整頁面所需的“靜態(tài)文件”:STATIC_URLSTATIC_ROOT

Django 會檢查是否STATIC_URL設(shè)置不是None,來尋找合適的前綴來使用,并且會自動回退使用MEDIA_URL。例如,如果你站點(diǎn)的 MEDIA_URL'http://uploads.example.com/' 并且 STATIC_URLNone

>>> 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對象

當(dāng)你訪問表單上的一個組件的media屬性時,返回值是一個forms.Media對象。就像已經(jīng)看到的那樣,表示 Media 對象的字符串,是在你的HTML頁面的<head> 代碼段包含相關(guān)文件所需的HTML。

然而,Media對象具有一些其它的有趣屬性。

素材的子集

如果你僅僅想得到特定類型的文件,你可以使用下標(biāo)運(yùn)算符來過濾出你感興趣的媒體。例如:

>>> w = CalendarWidget()
>>> print(w.media)
<link  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  type="text/css" media="all" rel="stylesheet" />

當(dāng)你使用下標(biāo)運(yùn)算符的時候,返回值是一個新的 Media對象,但是只含有感興趣的媒體。

組合Media對象

Media 對象可以添加到一起。添加兩個Media的時候,產(chǎn)生的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  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 的規(guī)則和組件上面一樣:定義可以為靜態(tài)的或者動態(tài)的。聲明的路徑和繼承規(guī)則也嚴(yán)格一致。

無論是否你定義了media, _所有_表單對象都有media屬性。這個屬性的默認(rèn)值是,向所有屬于這個表單的組件添加media定義的結(jié)果。

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

>>> f = ContactForm()
>>> f.media
<link  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>

如果你打算向表單關(guān)聯(lián)一些額外的素材 -- 例如,表單布局的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  type="text/css" media="all" rel="stylesheet" />
<link  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 文檔協(xié)作翻譯小組,原文:Integrating media

本文以 CC BY-NC-SA 3.0 協(xié)議發(fā)布,轉(zhuǎn)載請保留作者署名和文章出處。

Django 文檔協(xié)作翻譯小組人手緊缺,有興趣的朋友可以加入我們,完全公益性質(zhì)。交流群:467338606。