別のブログ記事用に、Djangoで簡単なアプリを作った。モデルがなく、単にView関数を呼び出してTemplateを出すだけ。
from django.shortcuts import render from django.views.generic import View # Create your views here. class IndexView(View): def get(self, request, *args, **kwargs): return render(request, 'myapp/index.html')
するとエラーが出た。
django.template.exceptions.TemplateDoesNotExist: myapp/index.html
このとき何をチェックすべきだろうか。
Templateのパスを確認する
自分がよく間違えるのが、Templateのパスの書き方。
公式ドキュメントを読んで、DjangoのTemplateの探し方を理解しておく必要がある。
Templateの探し方は、プロジェクトのsettings.pyの中にあるTEMPLATESの項目で規定されている。
デフォルトでは、プロジェクトを作ったあとは以下のような状態になっているはず。(Django2.1の場合)
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'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',
],
},
},
]
DIRSに何も入っておらず、APP_DIRSがTrueになっているので、Djangoはプロジェクト内の各アプリケーションの配下にあるtemplatesという名前のディレクトリ内を探索する。
そのため、単にアプリケーション配下にTemplateファイルを置いてもだめ。templatesというディレクトリを作る必要がある。
各アプリケーションのtemplatesディレクトリが探索の起点となるので、myapp/templates/myapp/index.html に置いたTemplateファイルをViewの中で指定するには、単にmyapp/index.html と書けばよい。
なお、探索の際はどのアプリケーションかを考慮せずに、最初にパスがマッチしたら探索終了となる仕様になっている。そのため、templates内にさらにディレクトリを切るなどして、名前空間を分けることが推奨されている。
ただ、今回の場合はmyapp/templates/myapp/index.htmlとなるようにファイルを作っていたので、パスの問題ではなかった。
INSTALLED_APPSを確認する
上記のTemplate探索にはもうひとつ前提がある。「各アプリケーションの配下にあるtemplatesディレクトリ」を探索するということは、アプリケーションと認識されていなければ探索されないということだ。
今回はそもそもここに原因があった。settings.pyのINSTALLED_APPSにmyappを登録するのを忘れていた。
INSTALLED_APPSには、そのプロジェクト内の全てのアプリケーションを登録しなければならない。
アプリケーションがあるパッケージ名をそのまま書いても動くことは動くが、推奨されているのは各アプリケーションのConfigurationクラスを登録することだ。
今回の場合、myapp.apps.MyappConfigを登録することで、無事にTemplateが表示されるようになった。