Djangoアプリをtutorial通り作って本番環境にデプロイしたらCSSや画像ファイルを読まなくなった場合の対処方法をメモします。
このスライドが分かりやすいのでこっちを読んだ方が良いかも
https://tell-k.github.io/djangocongressjp2019/#43
1. Djangoの静的ファイルの取り扱い
Djangoでは静的ファイルの扱いが開発中と本番環境で違います。これを切り替えるのがsetting.pyのDEBUG = True/Falseです。
DEBUG = Trueのときの/static/
djangoはアプリごとにフォルダ分けして開発するように作られていますので、静的ファイルであるCSSや画像ファイルもアプリのフォルダに置くようになっています。その為、開発中を意味するDEBUG = Trueの間はsetting.pyに書いたSTATIC_URLやSTATICFILES_DIRSで指定したフォルダ以下にある /static/ という名前のフォルダをすべて /static/ というAliasで扱ってくれます。
例えばproject/app1/static/base.css みたいなファイルがあった場合、
http://hoge.com/static/base.css であるものとして扱ってくれます。
本番環境でdjangoが/static/の配信をしない理由
本番環境でこの機能を使ってしまうとメインプロセスに無駄に負荷がかかってしまいますし、脆弱性の原因になり得ますので本番環境ではこの機能を切らないといけません。これを強制する為にApache2などでDjangoアプリをデプロイすると、DEBUG = Falseにしないとサンプル画面しか表示されないようになっています。
DEBUG = Falseのときの/static/
DEBUG = TrueのときはDjangoが/static/というAliasで静的ファイルを提供していましたがDEBUG = Falseになると提供しなくなるので、先程の例で言うとhttp://hoge.com/static/base.css は存在しないという事になります。これをApacheなどで提供してやれば開発中と同じ動作が得られます。
2. Apache2の設定手順
python manage.py collectstaticで静的ファイルを1箇所に集めて、集めた場所をApache2が/static/として配信するようにapahce2.confに書きます。Django Girls Tutorialでやってるやり方と同じです。
2-1. 静的ファイルを1箇所に集める
以下のようにプロジェクト直下にstaticというフォルダを作って集めてやります。
proj1
├── manage.py
├── mysite
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── myvenv
│ └── ...
├── static 静的ファイルを集める場所
│ ├── hoge.jpg
│ └── base.css
└── requirements.txt
静的ファイルを集める場所(STATIC_ROOT)を指定します。
以下では/home/xxxx/django/proj1/static/がSTATIC_ROOTになります。
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
collectstaticsコマンドを実行するとSTATIC_ROOTのPATHに静的ファイルを集めてくれます。
cd /home/xxxx/django/proj1
python manage.py collectstatics
2-2. 静的ファイルの場所をapache2.confに追加
/home/xxxx/django/proj1/static/base.css をhttp://hoge.com/static/base.css として扱いたいのでフォルダにAliasを付けてアクセス許可(Require all granted)します。
Alias /static/ /home/xxxx/django/proj1/static/
<Directory /home/xxxx/django/proj1/static>
Require all granted
</Directory>
設定を変更したのでApache2を再起動します。
sudo /etc/init.d/apache2 restart
2-3. 上手くいかない場合
collectstaticsは単にファイルをコピーするだけなので、STATIC_ROOTにファイルがコピーされているか確認すれば動作の確認が出来ます。
Apache2の登録が上手く出来ていない場合は、Apache2のエラーログに Django wsgi Apache2: 'AH01630: client denied by server configuration' が出る筈です。apache2.confの内容がSTATIC_ROOTと同じになっているか確認してください。
デフォルト設定のままならApache2のエラーログは以下で見られます。
tail -f /var/log/apache2/error.log