Django通用视图的正确模板位置?
根据Django文档,模板加载器会
从Django应用的文件系统中加载模板。对于每个在INSTALLED_APPS中的应用,加载器会查找一个名为templates的子目录。
继续说:
...然后get_template('foo.html')会按照以下顺序在这些目录中查找foo.html:
/path/to/myproject/polls/templates/
/path/to/myproject/music/templates/
所以...在我的"website"项目中,我有一个"www"应用。目录结构是/path/to/project/website/www/
我在"www"里面创建了一个"templates"目录,并在里面放了"page_list.html"(/path/to/project/website/www/page_list.html)
这个应用在"INSTALLED_APPS"中列出,但当我在urls.py中尝试这样做时:
url('^$', ListView.as_view(model=Page,))
我得到了"TemplateDoesNotExist"的错误,错误信息说django.template.loaders.app_directories.Loader正在寻找"/path/to/project/website/templates/www/page_list.html"或者/path/to/project/website/www/templates/www/page_list.html
如果我把模板放在website/www/templates/www里面,它就能正常工作...但我想知道为什么会这样。把一个templates文件夹放在应用文件夹里面,然后在templates目录里面再有一个同名的文件夹,听起来有点荒谬....
而且文档说应该在project/app/templates里面查找...我确实有
TEMPLATE_DIRS = [os.path.join(BASE_DIR, 'templates')]
虽然关于app_directories.Loader的文档没有说你需要这样做(我也尝试过去掉那个选项)。
这是怎么回事?我是不是做错了什么?是关于通用视图的事,还是还有其他问题?
1 个回答
你的问题是关于Django中基于类的视图自动命名模板的。比如,当你使用 django.views.generic.ListView
时,它会给你的模板自动生成一个名字 www/poll_list.html
。这个名字是通过 MultipleObjectTemplateResponseMixin 创建的。这个模板名是和 app_directory Loader 生成的前缀结合在一起的,所以你最终得到的路径是 /path/to/project/app/templates/www/poll_list.html
。
如果你不想要这个自动生成的名字,有几种不同的选择(按顺序):
- 在你的视图中使用 template_name 参数或属性。
- 创建一个 MultipleObjectTemplateResponseMixin 的子类,并去掉应用的前缀。然后在你的视图中使用这个子类。
- 不使用 app_directory loader。