【Django】settings.py内のBASE_DIRの意味と指す場所を解説
2020.04.26 /
世界的に人気があるプログラミング言語のPython。
そのPythonを使った有名なWebフレームワークDjangoですが、始めた当初はわからないことだらけでした。
わからないことの1つが、settings.pyの中身。
今回はそのsettings.pyに記載されている、BASE_DIRについて詳しく見ていきましょう。
BASE_DIRの指す場所
BASE_DIRはその名前の通り、ベースとなるフォルダ(ディレクトリ)を指しています。
その場所が具体的にどこであるかというと、プロジェクトを作成(django-admin startproject)した際にできるフォルダ内(manage.pyが入っている場所)を指しています。
言い換えるとアプリケーションのフォルダ(python manage.py startappで作成されるフォルダ)が入っているフォルダです。
ではなぜBASE_DIRがその場所を指していることがわかるのかを詳しく説明していきましょう。
settings.pyの中のBASE_DIR
settings.pyには下記のようにBASE_DIRが設定されています。
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
それではos.path.dirname(os.path.dirname(os.path.abspath(__file__)))についてみていきましょう。
まず__file__は、現在実行中のスクリプトファイル.pyのファイル名を取得します。
すなわち、ここではsettings.pyを取得します。
次にos.pathモジュールのos.path.abspathとos.path.dirnameです。
そもそもos.pathモジュールとは、ファイル名やパスを操作するための関数がたくさんあるモジュールです。
ではos.path.abspathは何をする関数なのかというと、引数に渡したパスの絶対パスを文字列として返します。
ちなみに絶対パスは英語でabsolute pathというので、abspathという関数名なんですね。
os.path.dirnameは引数の最後のパス区切り記号(/)までの文字列を返します。
よりわかりやすく説明すると、引数に指定されているパスの上位階層パスを返します。
2021/4/9追記
Pythonにpathlibが追加されたことにより、Django3.1以降からデフォルトのBASE_DIRの書き方が変更となりました。
以前まではos.pathを使用していましたが、最新のDjangoでは次のようにpathlibを使用しています。
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
BASE_DIRが示している場所には変更はないです。
注意点としては、os.pathとpathlibの両方を使用しないで、どちらかに統一した方がいいです。
例えばBASE_DIRではpathlibを使っているが、STATIC_ROOTにはos.pathを使っている場合は注意です。
from pathlib import Path
BASE_DIR = Path(__file__).resolve(strict=True).parent.parent
STATIC_ROOT = os.path.join(BASE_DIR, 'static_root')
なぜなら環境によって「500エラー」が発生することがあるからです。
もし500エラーが発生したら、pathlibとos.pathの共存が原因かもしれないです。
ちなみに上記のSTATIC_ROOTはpathlibを使って、以下のように記述することが可能です。
STATIC_ROOT = BASE_DIR / 'static'
お勧めとしては、os.pathは使わずにpathlibで統一するといいと思います。
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))とは
上記に示した各関数などの説明を踏まえ、
os.path.dirname(os.path.dirname(os.path.abspath(__file__)))が何を示すのか考えていきましょう。
fileはここではsetting.pyを表します。そしてos.path.abspathはsettings.pyの絶対パスを返すので、…/folder-name/project-name/settings.pyが返されます。
※…/folder-name/はお使いの環境により異なります
すると下記のようになります。
os.path.dirname(os.path.dirname(…/folder-name/project-name/settings.py)
os.path.dirnameは上位階層のパスを返し、かつos.path.dirnameは2回続くので、2階層上のパスが返ってきます。
これはつまり…/folder-name/を返すということです。
そしてこの場所はもうお分かりのようにプロジェクトを作成(django-admin startproject)した際にできるフォルダ内(manage.pyが入っている場所)を指しています。
2021/4/9追記
最新のDjangoで変更になったPath(__file__).resolve(strict=True).parent.parentも同じく、manage.pyが入っているフォルダを指しています。
まとめ
今回のポイントは次のようになります。
BASE_DIRはmanage.pyが入っている場所を指す
__file__は現在実行中のスクリプトファイル.pyのファイル名を返す
os.path.abspath関数は引数の絶対パスを返す
os.path.dirname関数は上位階層のパスを返す
settings.pyのBASE_DIRはDjangoにおいて重要な役割を果たしています。
これがわかっているのとわかっていないのでは、作成するWebアプリの幅が非常に狭まります。
今回学んだことはこの先も必要になる知識ですので、忘れずにいておいてください。