Python Django入門 初めの1歩からWEBアプリ作成までの流れ その6 静的ファイル(CSS, JS, 画像)の扱い方

みなさんこんにちは、ZeroTerasu(@ZeroTerasu)です。

今回は、Djangoにおける静的ファイル(CSS, JS, 画像)の扱い方について解説致します。

静的ファイルとは?

Djangoで扱う静的ファイルには下記のようなものがあります。

Djangoで扱う静的ファイルの例

CSSファイル

画像ファイル

JS(JavaScript)ファイル

これらのファイルは、ウェブサーバー上にあらかじめ用意されているものであり、クライアントからのリクエストに関わらず毎度同じファイルがレスポンスされてくるファイル群です。

会社概要ページや各ページに表示されるロゴマークなどはクライアント毎に変更されることが無いケースが多いため、静的コンテンツの例としてよく引用されます。

逆に、PHP、Python、JS等でクライアントからのリクエスト内容に応じてサーバー側で編集してレスポンスされるコンテンツを動的コンテンツと呼びます。

ブラウザに静的ファイルを認識させる方法

一般的なHTML, CSS, JSだけで構成されるウェブサイトにおいて、クライアントからのリクエストとそれに対してレスポンスが返される際のファイルのやり取りを例に説明します。(下記リンク先に説明があります。)

WEBサイトが表示される仕組の概要(図解)
WEBページが表示される仕組の概要.png

ここで、ウェブブラウザがどうやってCSS, JS, 画像を読み取っているか?を理解して頂ければ、Djangoが静的ファイルを読み込む流れについても理解して頂けると思います。

ウェブブラウザは、HTMLファイルを読み込む過程で、CSS, JS, 画像の各々独自のタグを読み込んだ際、都度サーバーにリクエストを送ります。

CSSタグ
<link rel="stylesheet" href="style.css">

↑ブラウザがこのタグを見つけると、HTMLファイルと同じフォルダ内の”style.css”を送ってもらうようにサーバーにリクエストします。

scriptタグ(JSファイルを読み込むためのタグ)
<script type="text/javascript" src="script.js"></script>

↑ブラウザがこのタグを見つけると、HTMLファイルと同じフォルダ内の”script.js”を送ってもらうようにサーバーにリクエストします。

imgタグ
<img src="logo.png" alt="ロゴです。">

↑ブラウザがこのタグを見つけると、HTMLファイルと同じフォルダ内の”logo.png”を送ってもらうようにサーバーにリクエストします。

Djangoでも同様に、テンプレート内のHTMLにCSS, JS, 画像それぞれの保存場所を明記してやれば良いです。

Djangoで静的ファイルを扱う際の流れ

次に、Djangoで静的ファイルを扱う際の流れについて確認します。

下記の図では、クライアントからhtmlファイルで構成されたページのリクエストがされた際のDjangoがレスポンスを返すまでの流れを図示しています。

Djangoが静的ファイルを返す流れ
HTMLファイルのリクエストとレスポンス

ブラウザからHTTPリクエストが投げられた際の処理の流れを下記に記載します。

①HTTPリクエスト(リクエスト内容は、html, CSS, JS, 画像ファイルで構成されるウェブページURLへのリクエストとします。まずはHTMLファイルだけがブラウザに返されます。)
開発サーバーがリクエストを受け取り、プロジェクトのurls.pyにリクエストを渡す。
プロジェクトのurls.pyがアプリケーションのurls.pyにリクエストを渡す。
アプリケーションのurls.pyがview.pyにリクエストを渡します。(④→➄は、app/urls.pyにリクエストページURLに対応したviews関数が実行されることが関連付けられているものとします。)
➄、⑥views.pyがtemplatesのhtmlファイルを要求し、view.pyにhtmlファイルが引き渡されます。ここで実行されるviews関数モデルテンプレートを利用してhtmlを生成します。また、静的ファイルを扱う場合、このhtml静的ファイルを扱うためのテンプレートタグを含ませておきます。
views.pyが開発サーバーにhtmlファイルを引き渡します。
開発サーバーは、ブラウザにhtmlファイルを引き渡します。(HTTPレスポンス)

さらに、htmlファイルを受け取ったブラウザは、静的ファイルのテンプレートタグで指定されたファイルのURLをサーバーにリクエストします。

このリクエストをDjangoの開発用ウェブサーバーソフトが受け取り、要求されたファイルのURL静的ファイルのURLである場合、そのファイルのURLに対応するファイルを静的ファイル保存先」に検索します。そして、該当ファイルが存在する場合、レスポンスとしてそのファイルを返します。この時、MTVは動作しません。

静的ファイルのリクエストとレスポンス

静的ファイルの保存先

☆ (重要) 静的ファイルの保存先は、下記のように決まっています。 ☆

プロジェクト名/アプリ名/static/アプリ名

静的ファイルの保存先

静的ファイルであることを認識させるためのSTATIC_URL

開発サーバーに静的ファイルであることを認識させるためには、ファイルのURLが「静的ファイルであること」を認識させる必要があります。

そのためには、ファイルのURL/STATIC_URLから始まる必要があります。

そこで、settings.pyに下記設定を追加します。

settings.py
STATIC_URL = 'static/

これによって、各静的ファイルのURLは、/static/アプリ名

HTMLファイルに静的ファイルを扱うためのテンプレートタグを設定

・テンプレートの中のそれぞれのタグをstaticテンプレートタグで置換します。

{% static ‘{検索先フォルダからのファイルの相対パス}’ %}

・それぞれのURLに、staticフォルダから先の相対パスとして記述します。

CSSファイル:<link rel=”stylesheet” href=”{% static ‘app/style.css’ %}”>

CSSタグ
{% load static %}
<link rel="stylesheet" href="{% static 'app/style.css' %}"

(補足)参考までにレンダリング後のhref=”static/app/style.css”となります。

JSファイル:<script type=”text/javascript” src=”{% static ‘app/script.js’ %}”>

scriptタグ(JSファイルを読み込むためのタグ)
{% load static %}
<script type="text/javascript" src={% static 'app/script.js' %}

(補足)参考までにレンダリング後のsrc=”static/app/script.js”となります。

imgファイル:<img src=”{% static ‘app/logo.png’ %}”>

imgタグ
{% load static %}
<img src="{% static 'app/logo.png' %}">

(補足)参考までにレンダリング後のsrc=”static/app/logo.png”となります。

プロジェクト直下にもstaticフォルダを作成する

上記までで各アプリ毎のstaticフォルダは作成出来ましたが、全アプリに共通で使用するCSSファイルや画像(会社のロゴマーク等)は、プロジェクト直下にstaticフォルダを設ける必要があります。

この時問題になるのが、プロジェクト直下のstaticフォルダをどうやって認識させるか?になります。

この解決法は非常にシンプルで、settings.pyに下記設定を追加するだけです。

見出し
import os
STATICFILES_DIRS = (
    os.path.join(BASE_DIR, "static/"),
)

これによってプロジェクト直下のstaticフォルダにファイルが存在するか確認されるようになります。

本番環境への適用

settings.pyのDebug=Falseに設定する。

静的ファイルを一か所に集約する

settings.pyに下記設定を追記します。

import os
STATIC_ROOT = os.path.join(BASE_DIR, "public_static") 
# 集約先は任意です。上記の場合、後のcollectstaticコマンド実行後、プロジェクト直下のpublic_staticというフォルダに集約されることになります。)

仮に、元々プロジェクト直下のstaticフォルダに集約していた場合は、下記のようにSTATICFILES_DIRSをコメントアウトして、STATIC_ROOTに新たに設定しなおす必要があります。

import os
STATICFILES_DIRS = (
    #os.path.join(BASE_DIR, "static/"),
)

STATIC_ROOT = os.path.join(BASE_DIR, "static/")

Nginxの設定

本番環境の場合、ウェブサーバー側の設定も変更する必要があります。

ここでは、Nginxの設定例を紹介します。

server {
    〜略〜

    location /static/ {
        alias /home/Django保存先フォルダ名/project/static/;
    }

    〜略〜
}

コメント

タイトルとURLをコピーしました