フォームアセット(Mediaクラス)
魅力的で使いやすいWebフォームをレンダリングするには、HTMLだけでなく、CSSスタイルシートも必要です。また、派手な「Web2.0」ウィジェットを使用する場合は、各ページにJavaScriptを含める必要があります。 特定のページに必要なCSSとJavaScriptの正確な組み合わせは、そのページで使用されているウィジェットによって異なります。
これが資産定義の出番です。 Djangoを使用すると、スタイルシートやスクリプトなどのさまざまなファイルを、それらのアセットを必要とするフォームやウィジェットに関連付けることができます。 たとえば、カレンダーを使用してDateFieldsをレンダリングする場合は、カスタムカレンダーウィジェットを定義できます。 このウィジェットは、カレンダーのレンダリングに必要なCSSおよびJavaScriptに関連付けることができます。 カレンダーウィジェットをフォームで使用すると、Djangoは必要なCSSファイルとJavaScriptファイルを識別し、Webページに含めるのに適したフォームでファイル名のリストを提供できます。
アセットとDjango管理者
Django Adminアプリケーションは、カレンダー、フィルターされた選択などのためにカスタマイズされたウィジェットの数を定義します。 これらのウィジェットはアセット要件を定義し、Django管理者はDjangoのデフォルトの代わりにカスタムウィジェットを使用します。 管理テンプレートには、特定のページでウィジェットをレンダリングするために必要なファイルのみが含まれます。
Django Adminアプリケーションが使用するウィジェットが気に入った場合は、独自のアプリケーションで自由に使用してください。 それらはすべてdjango.contrib.admin.widgets
に保存されます。
どのJavaScriptツールキットですか?
多くのJavaScriptツールキットが存在し、それらの多くには、アプリケーションを拡張するために使用できるウィジェット(カレンダーウィジェットなど)が含まれています。 Djangoは、JavaScriptツールキットを1つでも祝福することを意図的に避けています。 各ツールキットには、独自の相対的な長所と短所があります。要件に合ったツールキットを使用してください。 Djangoは任意のJavaScriptツールキットと統合できます。
静的定義としての資産
アセットを定義する最も簡単な方法は、静的定義としてです。 このメソッドを使用すると、宣言は内部Media
クラスになります。 内部クラスのプロパティは要件を定義します。
次に例を示します。
from django import forms
class CalendarWidget(forms.TextInput):
class Media:
css = {
'all': ('pretty.css',)
}
js = ('animations.js', 'actions.js')
このコードは、TextInput
に基づくCalendarWidget
を定義します。 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 src="http://static.example.com/animations.js"></script>
<script src="http://static.example.com/actions.js"></script>
可能なすべてのMedia
オプションのリストを次に示します。 必須のオプションはありません。
css
さまざまな形式の出力メディアに必要なCSSファイルを説明する辞書。
ディクショナリの値は、ファイル名のタプル/リストである必要があります。 これらのファイルへのパスを指定する方法の詳細については、パスに関するセクションを参照してください。
辞書のキーは出力メディアタイプです。 これらは、メディア宣言でCSSファイルによって受け入れられるのと同じタイプです:「all」、「aural」、「braille」、「embossed」、「handheld」、「print」、「projection」、「screen」、「tty」、および「テレビ'。 メディアタイプごとに異なるスタイルシートが必要な場合は、出力メディアごとにCSSファイルのリストを提供してください。 次の例では、2つのCSSオプションを提供します。1つは画面用、もう1つは印刷用です。
class Media:
css = {
'screen': ('pretty.css',),
'print': ('newspaper.css',)
}
CSSファイルのグループが複数の出力メディアタイプに適している場合、ディクショナリキーは出力メディアタイプのコンマ区切りのリストにすることができます。 次の例では、テレビとプロジェクターのメディア要件は同じです。
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">
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 src="http://static.example.com/animations.js"></script>
<script src="http://static.example.com/actions.js"></script>
<script src="http://static.example.com/whizbang.js"></script>
FancyCalendarウィジェットは、その親ウィジェットからすべてのアセットを継承します。 Media
をこのように継承したくない場合は、extend=False
宣言をMedia
宣言に追加します。
>>> 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 src="http://static.example.com/whizbang.js"></script>
継承をさらに制御する必要がある場合は、動的プロパティを使用してアセットを定義してください。 動的プロパティを使用すると、継承するファイルと継承しないファイルを完全に制御できます。
動的プロパティとしてのMedia
アセット要件のより高度な操作を実行する必要がある場合は、media
プロパティを直接定義できます。 これは、forms.Media
のインスタンスを返すウィジェットプロパティを定義することによって行われます。 forms.Media
のコンストラクターは、静的メディア定義で使用されているものと同じ形式のcss
およびjs
キーワード引数を受け入れます。
たとえば、カレンダーウィジェットの静的定義は、動的な方法で定義することもできます。
class CalendarWidget(forms.TextInput):
@property
def media(self):
return forms.Media(css={'all': ('pretty.css',)},
js=('animations.js', 'actions.js'))
動的media
プロパティの戻り値を作成する方法の詳細については、メディアオブジェクトのセクションを参照してください。
アセット定義のパス
アセットを指定するために使用されるパスは、相対パスまたは絶対パスのいずれかです。 パスが/
、http://
、またはhttps://
で始まる場合、絶対パスとして解釈され、そのままになります。 他のすべてのパスには、適切なプレフィックスの値が付加されます。 django.contrib.staticfiles アプリがインストールされている場合、アセットの提供に使用されます。
django.contrib.staticfiles を使用するかどうかに関係なく、完全にレンダリングするには、:setting: `STATIC_URL` および:setting:` STATIC_ROOT` 設定が必要です。ウェブページ。
使用する適切なプレフィックスを見つけるために、Djangoは:setting: `STATIC_URL` 設定がNone
でないかどうかを確認し、自動的に:setting:` MEDIA_URL` [の使用にフォールバックします。 X181X]。 たとえば、サイトの:setting: `MEDIA_URL` が'http://uploads.example.com/'
で、:setting:` 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 src="http://uploads.example.com/animations.js"></script>
<script src="http://othersite.com/actions.js"></script>
ただし、:setting: `STATIC_URL` が'http://static.example.com/'
の場合:
>>> w = CalendarWidget()
>>> print(w.media)
<link href="/css/pretty.css" type="text/css" media="all" rel="stylesheet">
<script src="http://static.example.com/animations.js"></script>
<script src="http://othersite.com/actions.js"></script>
または、 staticfiles が ManifestStaticFilesStorage を使用して構成されている場合:
>>> w = CalendarWidget()
>>> print(w.media)
<link href="/css/pretty.css" type="text/css" media="all" rel="stylesheet">
<script src="https://static.example.com/animations.27e20196a850.js"></script>
<script 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 src="http://static.example.com/animations.js"></script>
<script 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
オブジェクトを一緒に追加することもできます。 2つの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 src="http://static.example.com/animations.js"></script>
<script src="http://static.example.com/actions.js"></script>
<script src="http://static.example.com/whizbang.js"></script>
資産の順序
多くの場合、アセットがDOMに挿入される順序は重要です。 たとえば、jQueryに依存するスクリプトがあるとします。 したがって、Media
オブジェクトを組み合わせると、各Media
クラスでアセットが定義される相対的な順序が維持されます。
例えば:
>>> from django import forms
>>> class CalendarWidget(forms.TextInput):
... class Media:
... js = ('jQuery.js', 'calendar.js', 'noConflict.js')
>>> class TimeWidget(forms.TextInput):
... class Media:
... js = ('jQuery.js', 'time.js', 'noConflict.js')
>>> w1 = CalendarWidget()
>>> w2 = TimeWidget()
>>> print(w1.media + w2.media)
<script src="http://static.example.com/jQuery.js"></script>
<script src="http://static.example.com/calendar.js"></script>
<script src="http://static.example.com/time.js"></script>
<script src="http://static.example.com/noConflict.js"></script>
Media
オブジェクトをアセットと競合する順序で組み合わせると、MediaOrderConflictWarning
になります。
フォーム上の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 src="http://static.example.com/animations.js"></script>
<script src="http://static.example.com/actions.js"></script>
<script 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 src="http://static.example.com/animations.js"></script>
<script src="http://static.example.com/actions.js"></script>
<script src="http://static.example.com/whizbang.js"></script>