フォームアセット(メディアクラス)—Djangoドキュメント

提供:Dev Guides
< DjangoDjango/docs/3.2.x/topics/forms/media
移動先:案内検索

フォームアセット(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.jsactions.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">

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

または、 staticfilesManifestStaticFilesStorage を使用して構成されている場合:

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