Address
304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM

Django管理画面

VPSでDjango×Nginxの管理画面にCSSが適用されないのを解決する方法

DjangoアプリをVPSサーバーなど外部サーバーで開発・公開するときに管理画面にCSSが適用されない場合の解決方法

Django初心者がDjangoを使うとき最初から附属している開発用サーバーを起動させて管理画面(Django Administration)などをそのサーバー上でチェックすることが多いと思います

しかし附属の開発用サーバー以外のサーバー、たとえばVPSやレンタルサーバーなどでDjango環境を展開し、そこで管理画面などを表示させると何も対策をしていない場合はCSSが適用されていない状態になります。今回はそれを解決する方法を説明します。

(記事中ではフォルダもディレクトリも同じ意味だと思ってください)

今回の不具合と原因

不具合

VPSとして使っているXserver VPSにおいてDockerでNginxコンテナとDjangoコンテナを展開・連携させたうえで、Djangoアプリの学習をしていると管理画面が次の画像のようになりました。(Django附属の開発サーバーは起動させていません)

本来ならば(ダークモードのテーマの場合)次のようになるはずです。

Django管理画面

原因

この原因は管理画面にCSSが適用されていないことです。管理画面のHTMLのソースを見ると<head></head>部分に、CSSを読み込む設定はきちんと記述されています。管理画面のソースを見てみましょう。

<link rel="stylesheet" href="CSSファイルの場所">

という部分ですね。この「href=”CSSファイルの場所” 」が適切な設定になっていないことが原因です。読み込むCSSファイルが存在していない、あるいは、存在しているがその場所の指定が間違っているということになります。

実はDjangoの場合は開発用サーバーかそれ以外のサーバーかで、こうしたCSSなどの静的ファイルの扱い方に違いがあります。そのため開発用サーバーを使う場合とそれ以外とで設定の仕方が異なるわけです。

解決方法

公式ドキュメント情報

まずは以下の公式ドキュメントをご覧ください。

Django公式ドキュメント:静的ファイルをデプロイする¶

フォルダ構成

注意点:今回はVSCodeとDockerを連携させている状態での解説です

まず今回の私のVPS内部のフォルダ構成は次のようになっています。Dockerコンテナに接続している状態でのVSCode上の表示です。

フォルダ名役割
staticCSSなど静的ファイルのためのフォルダ
testprojectDjangoプロジェクトフォルダ
mysiteアプリフォルダ
pollsアプリフォルダ

testprojectフォルダの外側にstaticフォルダを作りました。これらを含む.devcontainerフォルダ(VSCode上での表示はWORK[DEV~])をまるごとNginxコンテナとDjangoコンテナにあるworkというフォルダにマウントしています。結果、NginxコンテナとDjangoコンテナの内部では、workというフォルダにstaticフォルダが存在していることになっています。ただし今はまだその中は空っぽだと思っておいてください。

これから以下の作業でそのstaticフォルダにCSSなどの静的ファイルを入れていきます。

mysite>setting.py

まずmysiteフォルダのsetting.pyで次の記述を探します。

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True 

この変数DEBUGの設定を次のようにTrueからFalseに変えます。

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = False

さらに同ファイルに次の記述を追加します。追加する場所はその下の画像を参考にしてください。(もともと存在していればそのままでOKです)

import os
BASE_DIR = Path(__file__).resolve().parent.parent

Path(__file__).resolve()は、それが記述されているPythonファイル(今回はsettings.py)の絶対パスを返すコードです。結果この変数BASE_DIRは、settings.pyが入ってるmysiteフォルダの2つ上のフォルダ(今回はDjangoコンテナの一番上のフォルダ)を意味します。

記述箇所はこの画像のようにしました。1つの例ですが。

次に同setting.pyの最後のほうに次の記述を加えます。

# どのフォルダ/ディレクトリから静的ファイルを配信するかを指定
STATIC_ROOT = os.path.join(BASE_DIR, "/work/static/")
# 静的ファイルにアクセスするために、ブラウザのURLとして使うフォルダの指定
STATIC_URL = '/static/'

Djangoのコマンド「python manage.py collectstatic」の実行

次にDjangoのコマンドで、

python manage.py collectstatic

を実行します。このコマンドは、上のsetting.pyで記述した変数STATIC_ROOTに設定したフォルダにCSSやJavaScriptなどの静的ファイルをいっきにまとめて放り込んでくれるコマンドです。

実際にそれらの静的ファイルが入っているか確認してみてください。

ここまでできれば、次はSTATIC_ROOTに置かれたファイルを STATIC_URLから配信できるようにWeb サーバの設定を行う作業です。

これでDjango用コンテナ>workフォルダ>staticフォルダの中に静的ファイルが全て集まりました。

このDjango用コンテナのworkフォルダは、VPSの.devcontarinerフォルダと同期していますので、VPS>.devcontainerフォルダにもstaticフォルダとその中身が登場します。

そしてその.devcontainerはまたNginxコンテナとも同期していますので、今度はNginxコンテナ>work>staticにも、Django用コンテナ>workフォルダ>staticの中身がそのまま出現します。

こうしてDjangoコンテナ内部の処理、VPSの.devcontainer内部の処理、そしてNginxコンテナ内部の処理が全て相互に同期します。

Nginxのconf

続いてNginxのconfに次の記述を追加します。記述箇所は下の画像を参考にしてください。私の場合はdefault.confというファイルです。

    location /static/ {
            root  /work/;
        }

項目rootには、Nginxコンテナ内部のフォルダworkを指定しています。/work/staticではなく、/staticを除いた「/work」だけとします。locationで指定した「/static/」の1つ上のフォルダまでにします。

Nginxの再起動

Nginxの設定ファイルを編集したのでNginxコンテナに入って、Nginxを再起動するコマンドを実行します。

Nginxコンテナに入るには、サーバー上のシェル(ターミナル)で、

docker container exec -it コンテナIDまたはコンテナ名 bash

コンテナ名やコンテナIDは、

docker ps

というコマンドでわかります。

無事にコンテナに入れれば、Nginx再起動(設定ファイルの再読み込み)コマンドとして、

nginx -s reload

を実行します。

こうしてNginxコンテナ>work>staticのフォルダが公開されることとなります。

動作確認

あとはブラウザで再びDjangoの管理画面にアクセスしてみてCSSが適用されているか確認して終わりです。

Django管理画面

上手くいきました。

http://ドメイン名またはサーバーIPアドレス/static/admin/css/base.css

これでCSSファイルにこのようなURLでアクセスできるようになり、いいかえるとHTML内部のCSSの記述として、

<link rel="stylesheet" href="/static/admin/css/base.css">

となりました。

なお私はDjangoアプリ用にVPSサービスとしてXserver VPSを使っています。とても使いやすく快適なのでプログラミング学習におすすめのVPSです。

愛を分かち合いましょう