ユーニックス総合研究所

  • home
  • archives
  • django-base-dir

DjangoのBASE_DIRの意味をわかりやすく解説

  • 作成日: 2021-08-16
  • 更新日: 2023-12-26
  • カテゴリ: Django

DjangoのBASE_DIRの意味をわかりやすく解説

Djangoではプロジェクトの設定をsettings.pyというファイルで管理することが出来ます。
このsettings.pyには色々な設定が書かれていて、Djangoはサイトを動かすさいにこの設定値を参照します。

このsettings.pyにはBASE_DIRという定数があらかじめ定義されています。
このBASE_DIRという定数はどういう値なのでしょうか?
この記事ではBASE_DIRの値について詳しく解説していきます。

具体的には↓を見ていきます。

  • 解説の前提とするプロジェクト
  • BASE_DIRの定義
  • __file__とは?
  • pathlibとは?
  • Pathの簡単な使い方
  • BASE_DIRの値の意味

解説の前提とするプロジェクト

今回、解説に使用するDjangoプロジェクトは↓のような構成になっています。

mysite  
├── manage.py  
└── mysite  
    ├── asgi.py  
    ├── __init__.py  
    ├── settings.py  
    ├── urls.py  
    └── wsgi.py  

django-admin startproject mysiteで作成した直後の状態です。

BASE_DIRの定義

Django(3.1.7付近)がsettings.pyに定義するBASE_DIRですが、↓のような定義になっています。

from pathlib import Path  

# Build paths inside the project like this: BASE_DIR / 'subdir'.  
BASE_DIR = Path(__file__).resolve().parent.parent  

なにやらpathlibというモジュールのPathというオブジェクトを使って、__file__という変数を参照しています。
そしてそれをresolve()して、parent.parentという風に属性を参照しています。

BASE_DIRの定義はこれらのコードの実行結果になります。
つまり、これらのコードを1つずつ見て行けばBASE_DIRの持つ値の意味がわかるということになります。

__file__とは?

まずは__file__変数から見ていきます。
__file__はPythonの組み込みの変数で、これにはファイル名が保存されています。
たとえばsettings.py内でこの__file__を参照した場合は、settings.pyのファイル名が保存されるということになります。

具体的にsettings.py内におけるこの__file__の値を見てみましょう。
↓のようなコードをsettings.pyに書きます。

print('settings.py: __file__ =', __file__)  

そしてpython manage.pyを実行します。
すると筆者の環境では↓のような値が出力されます。

settings.py: __file__ = /to/mysite/settings.py  

↑のように__file__には、__file__を参照しているファイルのフルパス名が保存されています。

pathlibとは?

関連記事:
Pythonのpathlibの今時な使い方

pathlibとはパスに関連する問題を解決するモジュールです。
pathlibにはPathオブジェクトが定義されていて、一般的にはこのPathオブジェクトをインポートして使います。

Pathオブジェクトには多数のパスに関連するメソッドが定義されています。
また、属性もあります。
このPathオブジェクトを操作することでパスの問題を解決することが可能です。

Pathの簡単な使い方

Pathの使い方を見てみます。
まずPathオブジェクトに__file__を渡します。
こうすると__file__の持つパスの値をPathオブジェクトで管理できるようになります。

path = Path(__file__)  
print(path)  
# /to/mysite/settings.py  

resolve()の意味

Pathオブジェクトのresolve()はどういうメソッドなんでしょうか?

Path.resolve - pathlib --- オブジェクト指向のファイルシステムパス — Python 3.9.4 ドキュメント

resolve()はパスを絶対パスに変換します。
そしてあらゆるシンボリックリンクを解決して、リアルなパスにします。

つまり↓のコードは

Path(__file__).resolve()  

__file__の持つ値をresolve()で解決して、絶対パスに変換しているということになります。
__file__の値を信用していないコードになるというわけです。
つまり__file__の値が相対パスだった場合でも絶対パスに変換することで、その後のコードをうまく動作させるという狙いがあります。
ちなみに__file__の値が必ず絶対パスであるという保証はないようです。なぜならドキュメントには「絶対パス」という記載がないからです。

parentの意味

parentの属性の意味は、現在のパスの上位ディレクトリの参照です。

PurePath.parent - pathlib --- オブジェクト指向のファイルシステムパス — Python 3.9.4 ドキュメント

__file__の値がたとえば/aaa/bbb/cccだっとします。
そうすると↓のコードは

print(Path('/aaa/bbb/ccc').parent)  
# /aaa/bbb  

↑のようにparent1つだけの場合は値は/aaa/bbbになります。
parentを2つ繋げた場合は、

print(Path('/aaa/bbb/ccc').parent.parent)  
# /aaa  

↑のように2つ上のディレクトリが参照されます。

BASE_DIRの値の意味

では以上のことを踏まえてBASE_DIRの値を見てみます。

BASE_DIRの値はPathオブジェクトで生成されます。
Path(__file__)__file__settings.pyのパスが保存されていて、それをPathで管理します。
そしてresolve()メソッドでパスを絶対パスに変換します。
さらにparent属性を2回参照して、2つ上のディレクトリを参照します。

つまり↓のコードは、

BASE_DIR = Path(__file__).resolve().parent.parent  
print('__file__ =', __file__)  
# __file__ = /to/mysite/settings.py  
print('BASE_DIR =', BASE_DIR)  
# BASE_DIR = /to/mysite  

↑のような結果になるわけです。
BASE_DIRが示しているパスはどこかと言うと、

mysite <---------------- ここがBASE_DIR  
├── manage.py  
└── mysite  
    ├── asgi.py  
    ├── __init__.py  
    ├── settings.py <--- ここが__file__  
    ├── urls.py  
    └── wsgi.py  

ということになります。

BASE_DIRの使い方

BASE_DIRPathオブジェクトなので、/でパスを合成することが出来ます。
たとえば↓のようにです。

print(BASE_DIR / 'abc/def.py')  
# /to/mysite/abc/def.py  

↑のようにすればパスを合成できるので、settings.pyでパスが必要な時はBASE_DIRの使用を検討してみてください。

おわりに

今回はDjangoのBASE_DIRについて詳しく見てみました。
BASE_DIRは利用頻度が高いので、あらかじめ定数化されています。
settings.pyを書く機会が増えればBASE_DIRの使用回数も増えるかもしれません。

🦝 < BASE_DIRはショートカット

🐭 < BASE_DIRを使ってパスを合成しよう