なぜDjangoアプリのディレクトリにはたくさんのtemplatesとstaticがあるのか。

Djangoのディレクトリ構成はLaravelやRailsといった類似ライブラリーとは大きく違った方針を取っています。
なぜ統一した「Template(Static)」ディレクトリを採用せずに「アプリケーションの要素か」を基準に区分しているか、それは各アプリケーションのViewの関心からディレクトリ構成を外すことができるからです。単一のコンポーネントの中にTemplateやStaticがあることによって`プロジェクトディレクトリ/templates/`の配置に振り回されることがなく、固有の差し替えが必要な場合は`プロジェクトディレクトリ/templates/`配下に差し替えたTemplateを配置することで差し替えをView等をいじることなく行うことが可能です。今回はDjangoにおけるディレクトリ構成の観点からTemplatesやStaticを扱う際にについて気を付けるべきところをまとめてみました。

## Templates/Static共通して言えること

Templates/Static共通の特性として以下が挙げられます。
- settings.py内に必要な設定を書くことでファイル検索ロジックが変更可能
- 名前がかぶったとき最初に見つかったファイルを適用

ファイル検索ロジックを変更できる機能そして、最初のファイルを適用する特性から思わぬところから名前空間の衝突によるバグが発生することがあります。そのためなのか、Djangoのプラクティスには「`プロジェクトディレクトリ/templates(static)/`**にすべてのテンプレートを集約するのが良い。**」という記述が時々みられます。確かに1回限りのWEBサイトを作る場合については、アプリケーションのモジュール化を行わないため、Templates/Staticの名前空間の問題を回避する一つの選択肢として検討してもいいかもしれません。しかしながら、WEBアプリを作成する際Templates・Static配下のディレクトリ構成がアプリケーションの関心に含まれてしまうことは、Viewの関心する範囲が大きくなってしまっている状態であることは留意し、アプリケーションのTemplateはできる限りアプリケーション内に閉じ込めましょう。

::: note
テンプレートエンジンの挙動についての仕様は「[テンプレートエンジンのサポート](https://docs.djangoproject.com/en/4.1/topics/templates/#support-for-template-engines)」に詳しく記載されています。
:::

## 公式ドキュメントにおけるTemplatesのディレクトリ構成についての言及

TemplatesはDjangoの[design-philosophies](https://docs.djangoproject.com/en/4.1/misc/design-philosophies/#template-system)で9つも言及されてるほど重要度の高い機能です。
チュートリアルではチュートリアル3、チュートリアル7、reusable-appsの3回にわたってTemplatesについての言及が行われています。
チュートリアル３では何も設定を行っていないときアプリケーションの`templates`配下を検索することとコラム「Template namespacing」内でアプリケーション同士でテンプレート名の衝突が起きたとき、Djangoは区別することができないためにアプリケーションにちなんだ名前空間を配置してほしいという記載があります。

#### Templatesの検索ロジック

チュートリアル3ではデフォルトの検索ロジックがアプリケーション配下の`templates`ディレクトリからloader.get_template()関数として指定されたものを検索してきます。
例えば以下のようなディレクトリを仮定し、**いずれかの**アプリのviews.py内で`loader.get_template('hoge.html')`が呼び出されたときを考えます。まず、app1,app2のtemplatesからhoge.htmlがあるかを検索します。app1のtemplatesに`hoge.html`があるのでそれをtemplateとして解釈します。
このような挙動をするため名前の衝突というリスクと常に隣り合わせです。チュートリアル内コラム「Template namespacing」では、（ex:`polls/templates/polls`）名前空間を作るようにというプラクティスが書かれています。
```
project/
    app1/
        templates/
            hoge.html
    app2/
        templates/
            huga.html
    project/
        settings.py
    manage.py
```

### 再利用性のためのtemplateの配置

「特定のサイト固有の要素」と「再利用ができる要素」として明確に区別し、再利用できる要素についてはアプリケーションのテンプレートディレクトリに配置した方が良いとチュートリアル7内で記載されています。これはreusable-apps内でアプリケーションをプロジェクトに依存させるのではなく自己完結させるためにテンプレートディレクトリをこのような配置にした方が良いと記載されています。

::: note
[テンプレートの継承](https://docs.djangoproject.com/en/4.1/ref/templates/builtins/#std-templatetag-extends)もTemplate構成にはなくてはならない概念のため一読してみるとよいでしょう。
:::


## Staticについて
Staticはチュートリアル[^1]ではチュートリアルにて作成したアプリケーション配下のStaticディレクトリ内に配置されています。Staticファイルに関する言及はチュートリアルでは少ないが、「[How to manage static files (e.g. images, JavaScript, CSS)](https://docs.djangoproject.com/en/4.1/howto/static-files/)」、「[How to deploy static files](https://docs.djangoproject.com/en/4.1/howto/static-files/deployment/)」ではStaticファイルの扱い方について詳しく言及されています。それらによると、StaticファイルはDjangoアプリケーションからではなくnginx等から直接配信することがパフォーマンスの観点から推奨されています。そのほかにStatic関係では注意しなければならないこととして以下が記載されています。
- Debugの値によって機能が変わる部分がある（runserver時に自動でstaticファイルを集める等）
- Templateと同様にstaticファイルは名前空間が分けられていないため、独自に名前空間のためのディレクトリを切る必要がある。

::: note
「[The staticfiles app](https://docs.djangoproject.com/en/4.1/ref/contrib/staticfiles/#module-django.contrib.staticfiles)」というStaticファイルのための設定や補助コマンドについてまとめて書かれているページも一緒に見ることで特にデプロイプロセスを考える際の助けになるかと思います。
:::

[^1]: [参考URL](https://docs.djangoproject.com/en/4.1/intro/reusable-apps/) advancedチュートリアルであるreusable-appsにはそれより前が終了した時点（＝Basicなチュートリアル終了時点）のディレクトリ構成が明示的に書かれている。今回はこれをチュートリアル終了時点のディレクトリ構成として扱います。



## まとめ

再利用するコードはプロジェクトのルートディレクトリやプロジェクトの設定を置くディレクトリに入れるのではなくアプリケーションに入れ、アプリケーション固有の命名をつけることでライブラリ化のハードルをぐっと下げることになります。Djangoのベストプラクティスの記事はありますが「なぜこのプラクティスがDjangoのドキュメントと違うのか」という観点で改めて公式Documentを読んで実際のコードに落とし込むことでよりライブラリーをうまく使ったアプリケーションを作っていきましょう。