Djangoプロジェクトのディレクトリ構成は非常にスマートに設計されていますが、同じ名前のフォルダがいくつかできてしまったりと分かりづらい部分があります。この記事ではよりわかりやすい構成を紹介するとともに、Djangoそのもののアーキテクチャについても解説します。
目次
Djangoのアーキテクチャ
まずはじめにDjangoそのもののアーキテクチャの全体像について学びましょう。
この時点で完璧に理解する必要はありません。ざっくりと全体像を頭に入れてから学習を開始することでこの先の理解がスムーズになります。
WebブラウザからWebサーバーにリクエストが届いたあと、Djangoは次のように処理を行い、レスポンスを返します。
- URLディスパッチャが URLconf に登録されたURLパターンにマッチするビューを探して呼び出す
- ミドルウェアが前処理を行う
- ビューがフォーム、モデル、テンプレートの各ファイルから表示する内容を生成しようとする
- データベースと通信し必要なデータを取得する
- 表示内容(ビュー)が生成される
- ミドルウェアが後処理を行う
- URLディスパッチャがレスポンスや例外をハンドリングする
Djangoは MVT(Model – View – Template)フレームワークと呼ばれることがありますが、アーキテクチャ的にはWebアプリケーションフレームワークの標準的な MVC(Model – View – Controller)モデルと変わりません。
MVCモデルの「View」がさらにテンプレートとビューに分割されているだけで、「Controller」の部分にはURLディスパッチャが相当します。
Djangoを使ってアプリケーションエンジニアが開発していくのは主に
- ビュー(views.py)
- モデル(models.py)
- テンプレート(テンプレートとなるHTMLファイル)
の3つです。
Djangoのわかりやすいディレクトリ構成
さて、前回の記事ではプロジェクトとアプリのディレクトリを実際に作成し、Webブラウザに Hello, World! と表示するところまで進めましたが、myappフォルダの中にmyappフォルダができたりと、これではどのフォルダが何の役割を果たしているのかわかりづらいです。
Django公式チュートリアルのディレクトリ構成
ちなみにこのままDjangoの公式チュートリアルを進めていくと、次のようなディレクトリ構成となります。
myapp という名前のフォルダが2つあったり、hello/templates/hello というディレクトリがあったりとなかなかわかりづらいです。
もちろん理由があってこのような構成になってはいるのですが、これだと同じ名前のファイルと間違えてミスをしやすかったり、構造的にも理解しづらいです。
これらの問題を解決するようにディレクトリを構成してみましょう。
いったん前回のプロジェクト(myappディレクトリ)は削除します。
config(アプリケーション全体の設定ディレクトリ)
まずは Windows PowerShell でプロジェクト全体のディレクトリ(django-tutorial)に入り、次のコマンドでDjangoプロジェクトを作成します。
django-admin startproject config .
このディレクトリはアプリケーション全体の設定などを置いておくフォルダなので config という名前にしておきます。
ディレクトリの中身は次のようになっています。
hello(アプリケーション個別のディレクトリ)
次に、個別のアプリケーション用のディレクトリを作成します。
ここでは hello という名前にしておきます。
python manage.py startapp hello
ディレクトリの中身は次のようになっています。
Djangoでは1つのプロジェクト(ここではdjango-tutorial)の中に個別のアプリケーション(ここではhello)を複数作成して運用するため、このようにプロジェクトフォルダの中に個別のアプリケーションフォルダを作成していきます。
config/settings.py にアプリを追加
個別のアプリを作成したら、config/settings.py に次のように記述して、Djangoがアプリを認識できるようにしましょう。
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'hello.apps.HelloConfig', # 作成したアプリを追加 ]
ここで追加するのはそのアプリ(今回はhello)の apps.py に記載されているクラス名です。
一部大文字になっているので注意しましょう。
URLの紐づけ
ユーザーが hello/ 以下にアクセスした場合のルーティングを hello ディレクトリの urls.py に任せるよう設定しましょう。
config/urls.py に次のように記述します。
from django.contrib import admin from django.urls import path, include # includeを追加 urlpatterns = [ path('admin/', admin.site.urls), path('hello/', include('hello.urls')), # hello/以下のルーティングはhello.urls.pyに任せる ]
helloディレクトリにurls.pyを作成してルーティングの記述をしておきましょう。
from django.urls import path from . import views urlpatterns = [ path('', views.index, name='index'), ]
static(静的ファイル用のディレクトリ)
プロジェクトディレクトリ(ここではdjango-tutorial)直下に static という名前で静的ファイル用のディレクトリを作成します。
WebアプリケーションではCSSやJavaScript、画像など、リクエストに応じて中身を変更することなくそのまま配信可能なファイルを静的ファイルと呼びます。
こちらもDjangoが認識できるよう settings.py に追記してあげましょう。
BASE_DIR = Path(__file__).resolve().parent.parent #BASE_DIRの位置 ・・・ STATIC_URL = 'static/' STATICFILES_DIRS = [BASE_DIR / 'static'] # 静的ファイルのディレクトリの場所
BASE_DIRの位置はデフォルトのままでいいはずですが、もし記述が異なっている場合はこの記述に変更しておいてください。
templates(テンプレート用のHTMLファイル用のディレクトリ)
プロジェクトディレクトリ(ここではdjango-tutorial)直下に templates という名前で静的ファイル用のディレクトリを作成します。
これはビューのテンプレートとなるHTMLファイル用のディレクトリです。
こちらもDjangoが認識できるよう settings.py に追記してあげましょう。
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [BASE_DIR / 'templates'], # テンプレート用のフォルダを追記 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ 'django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages', ], }, }, ]
現在のディレクトリ構成
ディレクトリ、ファイルの基本設定は以上です。
現在のディレクトリ構成を確認してみましょう。
この記事でやってきたものに加えて、staticやtemplateディレクトリに入るものの例として style.css や index.htmlファイルを配置しています。
公式チュートリアルをそのまま進めていった場合と比べて幾分か見やすく、どれが何用のディレクトリなのか分かりやすくなったと思います。
ローカルで開発する分にはこれで問題ありませんが、デプロイする場合はこれに加えて settings.py や urls.py に STATIC_ROOT に関する記述が必要になるためご注意ください。
例えば次のように settings.py に記述します。
STATIC_ROOT = /var/www/{BASE_DIR.name}/static'
また、config/urls.py には例えば次のように記述します。
urlpatterns = [ ︙ ]…+static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)