記事ページを表示中

Djangoで静的ファイル(イメージファイル、CSSファイル、Javascriptファイル)を使用する方法

記事No.63

更新日時2023年03月10日

バイオレットちゃん

DjangoでCSSファイルを使おうとするとエラーがでるわ…

では今回は、DjangoでCSSファイルなどの静的ファイルを扱う方法を解説するね。

スカーレット

バイオレットちゃん

静的ファイルの扱いかたが分かると、イメージファイルやJavaScriptファイルも扱えるようになりますか?

そうだよ!そういったファイルも問題なく扱えるよ!

スカーレット

設定方法

Djangoで静的ファイルを使用するには、以下のファイルを編集します。

  1. htmlファイル
  2. urls.pyファイル
  3. settings.pyファイル

htmlファイルへの記述

まず最初に、index.htmlの一番上の行に、以下を記述します。

{% load static %}
豆知識

{% %}で挟んで記述された部分を、「テンプレートタグ」と言います。上記の場合、loadテンプレートタグを使用しています。loadテンプレートタグは他のテンプレートタグを読み込む時に使います。上記の場合、loadテンプレートタグを使用してstaticテンプレートタグを読み込んでいます。

次に、読み込みたい静的ファイルを指定します。

今回は例として、CSSファイルを指定します。

<link rel="stylesheet" href="{% static 'appdir/css/style.css' %}" />

上のコードを見ると、先程loadテンプレートタグで読み込んだstaticテンプレートタグが使われている事が分かります。

staticテンプレートタグは、Djangoでレンダリングされると「staticフォルダへのパス」に変換されます。

「staticフォルダへのパス」は、urls.pyファイルで設定します。

Djangoは、クライアントからリクエストがあった時、今回記述したテンプレートタグをレンダリングしてHTMLファイルを生成します。そして、生成したHTMLファイルを送り返します。

ですので、

<link rel="stylesheet" href="{% static 'appdir/css/style.css' %}" />

とテンプレートタグを記述した場合でも、クライアントに返されるHTMLファイルは、

<link rel="stylesheet" href="/static/appdir/css/style.css" />

のようになります。

urls.pyへの記述

index.htmlへの記述が完了したら、次はurls.pyを設定します。

Djangoには、プロジェクトフォルダ内とアプリケーションフォルダ内それぞれにurls.pyファイルがありますが、ここで編集するのは、アプリケーションフォルダ内のurls.pyのほうです。

スカーレット

バイオレットちゃん

admin.pyが入っているほうがアプリケーションフォルダです!

まずはモジュールをインポートします。

from django.conf import settings
from django.conf.urls.static import static

from django.conf import settingsで、Djangoのプロジェクトフォルダ内にあるsettings.pyを読み込んでいます。

スカーレット

バイオレットちゃん

後でsettings.pyの中身も編集します!

urlpatternsを編集してインポートしたstaticを追加します。

staticの第一引数には、「staticフォルダへのパス」、第二引数には、「document_root=」と「staticフォルダのドキュメントルート」を記述します。

urlpatterns = [path('', views.index, name='index')] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

この例の場合、staticフォルダへのパスが「settings.STATIC_URL」でstaticフォルダへのドキュメントルートが「settings.STATIC_ROOT」となります。

豆知識

フォルダへのパスと、ドキュメントルートには次の関係があります。フォルダへのパスにアクセスがあった場合、実際に参照されるのはドキュメントルートに指定されたフォルダ。つまり、クライアント(ブラウザ)に表示されるのがフォルダへのパスで、そのパスへアクセスすると、サーバー内のドキュメントルートで指定されたフォルダを見る事ができます。

先程、index.htmlに記述した、

<link rel=”stylesheet” href=”{% static ‘appdir/css/style.css’ %}” />

の部分の、staticテンプレートタグは、DjangoでレンダリングされHTMLに変換されると、urls.pyに記述したstaticの第一引数に指定したフォルダへのパスに書き換わります。

今回の場合、第一引数に指定したフォルダへのパスは、「settings.STATIC_URL」となっています。

現段階では、settings.STATIC_URLにパスが代入されていないので、settings.pyファイルを編集して、settings.STATIC_URLにパスを代入します。

settings.pyへの記述

settings.pyの最後の行に以下を記述します。

STATIC_URL = '/static/'
STATICFILES_DIRS = [os.path.join(BASE_DIR, 'static')]
#STATIC_ROOT = os.path.join(BASE_DIR, 'static')

urls.pyでインポートしたsettingsは、ここで編集するsettings.pyファイルの事です。

urls.pyで、staticの第一引数に、変数settings.STATIC_URLを指定しましたが、この変数に’/static/’を代入します。

同じく、staticの第二引数に、変数document_root=settings.STATIC_ROOTを指定しましたが、この変数に、[os.path.join(BASE_DIR, ‘static’)]が入ります。

チェックポイント

第二引数で指定したのは、settings.STATIC_ROOTでしたが、Djangoの仕様により、STATIC_ROOTの代わりに、STATICFILES_DIRが参照されます。

[os.path.join(BASE_DIR, 'static')]は、manage.pyのあるフォルダ(BASE_DIR)内にあるstaticフォルダと、各アプリケーションフォルダ内にあるstaticフォルダを参照しています。

スカーレット

バイオレットちゃん

何故、STATIC_ROOTはコメントアウトされているのですか?

後で詳しく解説するけど、STATIC_ROOTはデプロイ時しか使わないからだよ!

スカーレット

コメントフォーム

STATICFILES_DIRの使い方

settings.pyで指定したSTATICFILES_DIRS = [os.path.join(BASE_DIR, ‘static’)]は開発中のみ参照されます。

本番環境では参照されないドキュメントルートです。

開発中は、各アプリケーションフォルダの中にstaticフォルダを入れて、その中で、imageファイルや、cssファイル、javascriptファイルを管理します。

STATICFILES_DIRS = [os.path.join(BASE_DIR, ‘static’)]は、それらアプリケーションフォルダ内にあるstaticフォルダを参照するドキュメントルートです。

豆知識

settings.py内で、DEBUG = Falseとなっている場合は、STATICFILES_DIRSは参照されません。STATICFILES_DIRSは開発中しか参照されない為です。DEBUG = Trueは、開発環境である事を意味し、エラーがあった場合に、そのエラー内容を表示させる事ができます。DEBUG = Falseは、本番環境である事を意味し、デプロイする際はDEBUG = Falseとします。

開発環境では、動的なファイルも静的なファイルもすべてDjangoがレスポンスを返していましたが、本番環境では、動的なファイルが要求された時のみDjangoにリクエストを送り、静的なファイルはNGINXなどのウェブサーバーがレスポンスを返すように設定します。

上の図のように、開発環境の場合、静的ファイル(静的コンテンツ)も動的ファイル(動的コンテンツ)もDjangoが返していました。

本番環境では、上の図のように静的ファイルのリクエストがあった場合はDjangoを使わずにウェブサーバーが単体でファイルを返します。動的ファイルのリクエストがあった場合のみDjangoにリクエストを送ります。

バイオレットちゃん

本番環境では、静的ファイルのリクエストはDjangoに届かないので、STATICFILES_DIRSは開発中しか参照されないのね!

そういう事!ちなみに、ウェブサーバーは、クライアントからのリクエストが、静的ファイルを求めているのか、動的ファイルを求めているかは、ウェブサーバーにアクセスしたURLによって判別しているよ。hoge.com/staticから始まるURLにアクセスしてきた場合は静的ファイルを求めている。それ以外のURLにアクセスしてきた場合は動的ファイルを求めている。といった具合です。

スカーレット

バイオレットちゃん

ウェブサーバーを構築する段階で、静的ファイルを返すURLと動的ファイルを返すURLを決めているのね!

例えば、クライアントが画像ファイル(静的ファイル)をリクエストした場合は、ウェブサーバーがレスポンスを返しますが、クライアントから送られてくる値によって返されるファイルが変わるような動的なファイルをリクエストした場合は、ウェブサーバーは、Djangoが動いているアプリケーションサーバーに仕事を振り、Djangoが処理できる設定をします。

このように仕事を振り分けたほうが、静的ファイルを速く返せる為、DJangoでは、このような仕様になっています。

バイオレットちゃん

ここらへんの事はウェブサーバーの知識が無いとイマイチよく分からないわ…

NGINXなどのウェブサーバーを使った事があるなら、クライアントからのリクエストを直接ウェブサーバーで返したり、アプリケーションサーバーに振り分けたりした経験があるからイメージしやすいと思うけど、そういった経験が無い場合は、理解するのちょっと難しいかも。

スカーレット

コメントフォーム

STATIC_ROOTの使い方

Djangoで作成したサービスをデプロイする時は、ウェブサーバーに、静的なファイルを置くフォルダを用意しておきます。

静的なファイルをウェブサーバーに置いておく事で、静的なファイルをリクエストされた際、ウェブサーバーのみで対応が可能になるからです。

上の図のように、ウェブサーバーにDjangoプロジェクトフォルダを配置し、そのフォルダの中にあるstaticフォルダに静的なファイルを集めておくと管理がしやすいです。

各アプリケーションフォルダ内のstaticフォルダにある静的ファイルを、プロジェクトフォルダ内のstaticフォルダに集めるコマンドが、collectstaticです。manage.pyがあるフォルダ内(プロジェクトフォルダ)で以下を実行します。

python manage.py collectstatic

collectstaticコマンドは、settings.pyに記述したSTATIC_ROOTに、各アプリケーション内のstaticフォルダにある静的ファイルを全て集めてくれます。

Django管理画面のCSSが本番環境で反映されない場合、collectstaticコマンドで管理画面アプリケーションの静的ファイルを集めていないからです。

スカーレット

バイオレットちゃん

開発中はアプリケーションフォルダ内のstaticフォルダも参照されるけど、本番ではプロジェクトフォルダ内のstaticフォルダしか参照されないからですね。

settings.pyに以下のように記述すると、STATIC_ROOTを設定する事ができます。

STATIC_ROOT = os.path.join(BASE_DIR, 'static')

この例の場合、BASE_DIR(manage.pyがあるフォルダ)内にあるstaticフォルダが指定されています。

STATIC_ROOTは、collectstaticコマンドを使用する時だけ参照できるようにすれば良いので、開発時はコメントアウトしておいて下さい。

スカーレット

NGINXなどでウェブサーバーを構築する際は、静的なファイルへのアクセスは、STATIC_ROOTで指定したドキュメントルートを参照するように設定します。

コメントフォーム

著者情報

名前:スカーレット
2010年からWEBサイトやWEBアプリを作成しています。最初は趣味でブログを書いていましたがSEOを勉強するのが楽しくなり、そのままブロガーとして独立しました。その後、記事を書くだけでは物足りなくなり自分でWEBアプリの作成をスタート。現在はブロガー兼プログラマーとして活動しています。このWEBアプリ(ブロトーク)もDjangoで自作しました。ブロトークはブログとSNSを合体させたようなWEBアプリです。ブログを読んで気づいた事や感想などあれば、気軽にメッセージを送って頂ければと思います。WEB技術を一緒に勉強していけたらと思います。