---
title: "フォームアセット (Media クラス)"
version: 3.1
locale: ja
source: https://docs.djangoproject.com/ja/3.1/topics/forms/media/
canonical: https://djangodocs.dev/ja/3.1/topics/forms/media/
---
# フォームアセット (`Media` クラス)

魅力的で使いやすいウェブのフォームを作るには、HTML だけでは不十分です - CSS スタイルシートも必要です。さらに豪華な "Web2.0" ウィジェットを使いたければ、JavaScript を各ページに配置する必要もあるでしょう。あるページに必要な CSS と JavaScript の組み合わせは、そのページに使用されるウィジェットによって異なります。

This is where asset definitions come in. Django allows you to
associate different files -- like stylesheets and scripts -- with the
forms and widgets that require those assets. For example, if you want
to use a calendar to render DateFields, you can define a custom
Calendar widget. This widget can then be associated with the CSS and
JavaScript that is required to render the calendar. When the Calendar
widget is used on a form, Django is able to identify the CSS and
JavaScript files that are required, and provide the list of file names
in a form suitable for inclusion on your Web page.

> **アセットと Django Admin**
>
> The Django Admin application defines a number of customized
> widgets for calendars, filtered selections, and so on. These
> widgets define asset requirements, and the Django Admin uses the
> custom widgets in place of the Django defaults. The Admin
> templates will only include those files that are required to
> render the widgets on any given page.
>
> If you like the widgets that the Django Admin application uses,
> feel free to use them in your own application! They're all stored
> in `django.contrib.admin.widgets`.

> **Which JavaScript toolkit?**
>
> Many JavaScript toolkits exist, and many of them include widgets (such
> as calendar widgets) that can be used to enhance your application.
> Django has deliberately avoided blessing any one JavaScript toolkit.
> Each toolkit has its own relative strengths and weaknesses - use
> whichever toolkit suits your requirements. Django is able to integrate
> with any JavaScript toolkit.

## 定数として定義されたアセット

アセットを定義する最も簡単な方法は、定数とすることです。この方法を利用するには、内部 `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 src="http://static.example.com/animations.js"></script>
<script src="http://static.example.com/actions.js"></script>
```

以下は指定可能な `Media` オプションです。必須のものはありません。

### `css`

様々な形式の出力メディアに対して、必要な CSSファイルを定義するディクショナリです。

ディクショナリの値はファイル名のタプルかリストで指定します。ファイルのパスを指定する方法は [パスの章](#form-asset-paths) を参照してください。

ディクショナリのキーは、出力するメディアタイプを表します。これらは CSS ファイル認識可能なメディアタイプと同じです: 'all'、'aural'、'braille'、'embossed'、'handheld'、'print'、'projection'、'screen'、'tty'、'tv'。メディアタイプに応じたスタイルシートを提供する必要がある場合、各出力メディアに対して CSS ファイルを作成してください。以下の例は 2 つの CSS オプションを提供します -- 1 つはスクリーン用でもう一つは印刷用です:

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

1 つの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 ファイルを定義したタプルです。ファイルのパスを指定する方法は [パスの章](#form-asset-paths) を参照してください。

### `extend`

`Media` 宣言に対する継承動作を定義する真偽値です。

デフォルトでは、定数の `Media` 定義を使用するすべてのオブジェクトは、親ウィジェットに紐付いたすべてのアセットを継承します。この挙動は、親ウィジェットがどのように自身の要件を定義しているかに関わらず発生します。例えば、上の例にあるベーシックな Calendar ウィジェットを拡張するには:

```
>>> 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` を追加します:

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

継承をより詳細にコントロールするにあｈ、[動的なプロパティ](#dynamic-property) を使ってアセットを定義してください。 動的なプロパティを使えば、どのファイルを継承し、また継承しないかを完全にコントロールできます。

## 動的プロパティとしての `Media`

アセット要件のより詳細な操作が必要な場合、`media` プロパティを直接定義することができます。これは、`forms.Media` のインスタンスを返すウィジェットプロパティを定義することで実現できます。`forms.Media` に対するコンストラクタは、定数によるメディア定義と同様の形式で、`css` と `js` のキーワード引数を認識します。

例えば、上記例で扱ってきた Calendar Widget に対する定数の定義は、動的な方法では以下のように定義できます:

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

動的な `media` プロパティに対する戻り値を構成する方法については、Media objects\`\_ を参照してください。

## アセット定義内のパス

アセットを定義するためのファイルパスには、相対および絶対パスのどちらも使えます。パスが `/`、`http://`、`https://` のいずれかで始まる場合は絶対パスとして認識され、そのまま使用されます。それ以外のパスには適当な接頭辞が追加されます。[`django.contrib.staticfiles`](/ja/3.1/ref/contrib/staticfiles/#module-django.contrib.staticfiles) アプリケーションがインストールされている場合、アセットを提供するために使用されます。

mod:django.contrib.staticfiles を使うかどうかに関わらず、ウェブページを完全に表示するために [`STATIC_URL`](/ja/3.1/ref/settings/#std-setting-STATIC_URL) と [`STATIC_ROOT`](/ja/3.1/ref/settings/#std-setting-STATIC_ROOT) の設定が必要となります。

適切な接頭辞を特定するため、Django [`STATIC_URL`](/ja/3.1/ref/settings/#std-setting-STATIC_URL) 設定が `None` でないかチェックし、自動的に [`MEDIA_URL`](/ja/3.1/ref/settings/#std-setting-MEDIA_URL) を使うようフォールバックします。例えば、サイトに対する [`MEDIA_URL`](/ja/3.1/ref/settings/#std-setting-MEDIA_URL) が `'http://uploads.example.com/'` で [`STATIC_URL`](/ja/3.1/ref/settings/#std-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>
```

一方、[`STATIC_URL`](/ja/3.1/ref/settings/#std-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`](/ja/3.1/ref/contrib/staticfiles/#module-django.contrib.staticfiles) が [`ManifestStaticFilesStorage`](/ja/3.1/ref/contrib/staticfiles/#django.contrib.staticfiles.storage.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` objects

ウィジェットやフォームの `media` 属性に応答指令信号を送ると、`forms.Media` オブジェクトが戻り値となります。すでに見たように、`Media` オブジェクトの文字列表現は HTMLで、HTML ページ内の `<head>` ブロックに関連ファイルを含める必要があります。

ただし、`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` 宣言を定義したかどうかに関わらず、*すべての* Form オブジェクトは `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>
```

If you want to associate additional assets with a form -- for example,
CSS for form layout -- add a `Media` declaration to the form:

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