◀ 15.

djangoにおける静的(static)ファイルの置き場所と読み込み(画像、css、js )

▶
この記事の要点
  • アプリ単位の静的ファイルは アプリ名/static/アプリ名/ の下に css・js・img を置く
  • static の下にもう一段アプリ名フォルダを挟むのは、別アプリの同名ファイルと衝突させないため(名前空間)
  • テンプレートでは {% load static %} の後、{% static 'app1/css/sample.css' %} で URL を生成する
  • 開発中(DEBUG = True)は runserver が自動で配信。本番(DEBUG = False)では配信されない
  • 本番は STATIC_ROOT を設定して collectstatic で 1 か所に集め、Nginx や WhiteNoise で配信する
  • プロジェクト共通の静的ファイルは STATICFILES_DIRS で指定する(別記事)

Django で画像・CSS・JavaScript などの静的(static)ファイルを置く場所には、アプリ単位で作る方法とプロジェクト単位で作る方法の 2 つがあります。本稿ではアプリ単位でのディレクトリ作成方法と、開発・本番それぞれでの読み込みの仕組みを記述します。プロジェクト単位で作る方法はこちらを参照してください。

前提の設定(settings.py)

startproject で作ったプロジェクトなら、次の設定は最初から入っています。消していないか確認します。

INSTALLED_APPS = [
    # ...
    'django.contrib.staticfiles',   # 静的ファイルを扱うアプリ
    'app1',                         # 自分のアプリも登録しておく
]

STATIC_URL = 'static/'              # 静的ファイルの URL の接頭辞

アプリが INSTALLED_APPS に登録されていないと、そのアプリの static フォルダは探索されません。

静的ファイル(画像、css、js)を格納するディレクトリ作成

アプリケーションフォルダ直下に static フォルダを作成し、さらに static フォルダ直下にアプリケーション名のフォルダを作成します。以下、アプリケーション名が app1 の場合の例です。

app1
    -- static
        -- app1
            -- css
            -- js
            -- img

css、js、img フォルダを作成して、その配下にそれぞれのファイルを格納します。開発サーバーでは、以下の URL で静的ファイルにアクセスすることができます。

http://localhost:8000/static/app1/css/sample.css

なぜ static の下にアプリ名のフォルダを作るのか

Django は静的ファイルを探すとき、INSTALLED_APPS に並んだ各アプリの static フォルダを順番に見て、最初に見つかった同名ファイルを使います。もし app1 と app2 の両方に static/css/style.css があると、{% static 'css/style.css' %} はどちらか一方にしか解決されず、もう一方は使えません。

static/app1/css/style.css のようにアプリ名を一段挟めば、パスが app1/css/style.css と app2/css/style.css に分かれて衝突しません。テンプレートの templates/アプリ名/ と同じ考え方の「名前空間」です。

テンプレートからの読み込み

テンプレート(html ファイル)から静的ファイルを読み込む場合は以下のように指定します。

{% load static %}
<!DOCTYPE html>
<html lang="ja">
<head>
  <link rel="stylesheet" href="{% static 'app1/css/sample.css' %}">
</head>
<body>
  <img src="{% static 'app1/img/logo.png' %}" alt="ロゴ">
  <script src="{% static 'app1/js/main.js' %}"></script>
</body>
</html>

{% load static %} はテンプレートファイルごとに必要です。親テンプレートで読み込んでいても、{% extends %} した子テンプレートで {% static %} を使うなら、子でも書きます。URL を /static/... と直書きせず {% static %} を使うと、STATIC_URL を CDN の URL に変えたときもテンプレートを直さずに済みます。

本番環境での配信(DEBUG = False のとき)

runserver が静的ファイルを自動で返すのは DEBUG = True の開発中だけです。本番で DEBUG = False にすると、CSS や画像が 404 になり、デザインが崩れた画面になります。本番では次の手順で配信します。

  1. settings.py に集約先 STATIC_ROOT を設定する
  2. python manage.py collectstatic を実行し、全アプリの static をそこへコピーする
  3. Nginx / Apache で STATIC_URL へのリクエストを STATIC_ROOT から返す。または WhiteNoise ミドルウェアで Django 自身に配信させる
# settings.py
STATIC_URL = 'static/'
STATIC_ROOT = BASE_DIR / 'staticfiles'   # collectstatic の出力先(自分で作ったフォルダとは別にする)
python manage.py collectstatic
# Nginx の設定例
location /static/ {
    alias /path/to/project/staticfiles/;
}

設定項目の違い

設定役割
STATIC_URL静的ファイルの URL の接頭辞(/static/ など)
アプリの static/ フォルダアプリ単位の置き場所。設定なしで自動的に探索される
STATICFILES_DIRSアプリに属さない、プロジェクト共通の置き場所を追加する
STATIC_ROOT本番用に collectstatic で集める出力先。手でファイルを置く場所ではない
MEDIA_URL / MEDIA_ROOTユーザーがアップロードしたファイル用。静的ファイルとは分けて管理する

うまく読み込めないときの確認方法

  • どのファイルに解決されるか調べる: python manage.py findstatic app1/css/sample.css を実行すると、実際に使われるファイルのパスが表示される。見つからなければ置き場所かパスのつづりが違う
  • 404 になる: アプリが INSTALLED_APPS にない、フォルダ名が statics などになっている、runserver を再起動していない(新しく作った static フォルダは再起動後に認識される場合がある)
  • Invalid block tag ... 'static': そのテンプレートで {% load static %} を書き忘れている
  • CSS を変更しても反映されない: ブラウザのキャッシュ。スーパーリロード(Ctrl+F5)で確認する。本番ではファイル名にハッシュを付ける ManifestStaticFilesStorage を使うとキャッシュの問題を避けられる
  • 本番だけ崩れる: collectstatic の実行忘れ、または Web サーバーの alias のパスの誤り

関連

Post Share
子ページ

子ページはありません

同階層のページ
  1. 環境構築とプロジェクト/アプリの作成
  2. MVC(MVT)のそれぞれの使い方と説明
  3. データベースへの接続と操作
  4. Django Administration
  5. git管理
  6. エラー一覧
  7. バージョンの確認方法
  8. ログ出力方法
  9. SQLのログ出力方法
  10. ログのローテート設定
  11. settings.pyの定数にアクセスする方法
  12. 本番環境へのインストールとアプリのデプロイ(apache編)
  13. 本番環境へのインストールとアプリのデプロイ(nginx編)
  14. djangoアプリの本番の開始URLを変更する
  15. 静的(static)ファイルの置き場所と読み込み(画像、css、js )
  16. CSRFトークンをAjaxで使用する方法
  17. ajaxの使用例(POST編)
  18. ファイルのアップロードとファイルの名前
  19. クイックスタート/チュートリアル
  20. ログイン機能
  21. テンプレート側のログイン判定
  22. ビュー側のログイン判定
  23. 管理者ユーザーの作成/判定と管理画面
  24. モデルのjson化とレスポンス
  25. runserverでポートを指定する方法
  26. cronによるバッチ実行
  27. テンプレートで利用する共通のcontextを定義する方法
  28. プログラムが本番サーバーで反映されない場合の対処法
  29. APIの作成
  30. cron用コマンド・ファイルの作成