投稿日:2019年11月26日
Djangoは簡単にWebアプリケーションを作成できるフレームワークです。この記事は初心者の方向けのDjangoチュートリアルです。
ここまでの記事で基本的なブログの機能については実装できました。しかし、サイトを見てみると白いページに黒い文字がならんでるだけでなんだか寂しいですね。
ここからのPartではCSSでの簡単なデザインをしていきます。
そして今回の記事はそのスタートとしてDjangoの静的ファイル管理ツールcollectstaticについてその簡単なと必要な設定について書いていきます。
Djangoでは静的ファイルをmanage.pyのcollectstaticというコマンドで管理します。このコマンドは全てのアプリケーションのディレクトリの静的ファイルを一つにまとめる機能を持ちます。これによってサードパーティのアプリケーション(他の誰かが作ったライブラリ)をプロジェクトにインストールしたときにも、collectstaticがまとめたディレクトリだけを公開すれば必要な全ての静的ファイルが公開できるわけです。
実際のプロジェクトを開発する際にはcollectstaticを使う流れは下の様になるでしょう。
collectstaticは全てのアプリケーションのディレクトリの静的ファイルを探しにいくため、静的ファイルはアプリケーションのどれかのディレクトリにはいっている必要があります。
しかし、開発する上で静的ファイルがあちらこちらに散らばるのは個人的に少し使いづらく感じます(templateについても同様)。静的ファイルでは基本的な開発は決まった一つのディレクトリで行い、プロジェクトの規模が大きくなったりアプリケーションを再利用・またはパッケージとして公開するときに、はじめてアプリケーションごとに分割するのが良いでしょう。
今回はcollectstaticの設定を少しだけカスタマイズして静的ファイルのディレクトリをひとつにまとめられるようにします。この開発方法はあくまで僕個人が開発しやすいと感じるものなので、この管理方法にとらわれず好きな管理方法で開発してください。
collectstaticは以下の様なルールでファイルを一つの場所にまとめます。
デフォルトではSTATIC_ROOTは設定されていないため必ずここの設定はする必要があります。そのままcollectstaticをしようとすると以下の様にエラーが出力されます。
$ python manage.py collectstatic
[...]
django.core.exceptions.ImproperlyConfigured: You're using the staticfiles app without having set the STATIC_ROOT setting to a filesystem path.
例えば特に何も考えずプロジェクトルートの直下でstaticという名前のディレクトリで管理する場合には以下の様な設定になるでしょう。
[...]
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
[...]
STATIC_ROOT = os.path.join(BASE_DIR,"static")
この状態でblogアプリケーションに新しくstaticディレクトリを作ってみましょう。アプリケーションごとに静的ファイルを管理する場合には、慣習として更にその中にアプリケーション名のディレクトリを作成し、その中でそれぞれjs、cssを管理します。
sample_blog/blog/static/
└── blog/
├── css/
│ └── sample.css # 空ファイル
└── js/
└── sample.js # 空ファイル
この状態でcollectstaticをすると
sample_blog/static/
├── admin
│ ├── css
│ ├── fonts
│ ├── img
│ └── js
└── blog
├── css
│ └── sample.css
└── js
└── sample.js
この様にアプリケーションのstaticディレクトリの中身がSTATIC_ROOTで指定したディレクトリにあつまりました。
もちろんDjangoの推奨するアプリケーションごとの静的ファイルの管理は、ソースの再利用という思想の基には非常に良い設計だと思います。
しかし、cssファイルやjsファイルがいろんなディレクトリに別れどこにあるかひと目でわからないプロジェクトでは、実際に開発する段階でどうなるでしょう?例えばデザイナーはいろんなディレクトリを行ったり来たりし、またプロジェクト管理者もどのディレクトリを誰が管理すれば良いのかばかりに気を取られてしまうかもしれません。
そこで僕が行っている管理方法では、プロジェクト全体の静的ファイルを一つのディレクトリにまとめて管理します。このためにはSTATICFILES_DIRSの設定を追加して上げればOKです。
今回はプロジェクトディレクトリの中にstaticディレクトリを作りそこでプロジェクト全体の静的ファイルを管理することにします。
[...]
STATICFILES_DIRS = [
("", os.path.join(BASE_DIR, "sample_blog/static")),
]
それとurlの設定を追加してあげましょう。
from django.urls import path, include
from django.contrib import admin
urlpatterns = [
path('admin/', admin.site.urls),
path('blog/', include('blog.urls', namespace='blog')),
]
# 以下が追加部分
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
from django.conf import settings
if settings.DEBUG:
urlpatterns += staticfiles_urlpatterns()
このurlの設定は開発中のデバッグに必須のものになります。基本コピペでOKです。
では実際にまとめましょう。と、その前にはじめ作成したblogのstaticディレクトリはもう使わないので削除しておいてください。
プロジェクトディレクトリに新たにstaticディレクトリを作成し以下のような構成にします。
sample_blog/sample_blog/static/
├── css/
│ └── sample.css # サンプルの空ファイル
├── js/
│ └── sample.js # サンプルの空ファイル
あとはcollectstaticコマンドをうってあげましょう。
$ rm -r -f blog/static
$ python manage.py collectstatic --clear
collectstaticの--clearオプションはSTATIC_ROOTのディレクトリの中を一端空にしてもう一度いちから集め直すというオプションです。設定を変えた後など、staticディレクトリにゴミファイルを残したくない場合にはこのオプションをつけましょう。
以下の様に静的ファイルをまとめる事ができます。
sample_blog/static/
├── admin/
│ ├── css/
│ ├── fonts/
│ ├── img/
│ └── js/
├── blog/
│ ├── css/
│ └── js/
├── css/
│ └── sample.css
└── js/
└── sample.js
開発が進んでサーバーにデプロイした後はcollectstaticであつめられた静的ファイルのディレクトリ(STATIC_ROOT)がそのまま公開されると思います。その場合静的ファイルの内容を変更しようとしたときには注意が必要です。ファイルの配信の設定をみてSTATIC_ROOTのディレクトリに静的ファイルのオリジナルがあると勘違いしてしまう人が出てくることがあるのです。
その勘違いのまま静的ファイルの内容を変更するとおそらく、STATIC_ROOTの中身に編集を加えてしまうでしょう。しかし、実際にこのディレクトリはcollectstaticによって本来の静的ファイルがコピーされてまとめられたディレクトリでしかありません。
そこを編集しても次collectstaticコマンドが実行されたときにオリジナルに上書きされてしまうのです。
つまり僕が言いたいのは...
静的ファイルの実体がどこにあるかはプロジェクトのメンバーに必ず共有しましょう!!