转载自 https://blog.youkuaiyun.com/sinat_30545941/article/details/77131491
django 通过 urls.py 路由寻找到 view 视图函数,在视图函数中通常会通过 get_template 函数加载模板。在刚创建好项目的时候,创建一个 app,如果直接在视图函数中返回 html 需要这样写:
def mytest(request):
t = loader.get_template("homepage1.html")
return HttpResponse(t.render())
- 1
- 2
- 3
这样的话,如果在 app 目录下创建 template 文件夹,并在其中创建 homepage1.html,就可以页面中就会显示除该 html 的内容。
但如果我创建另外一个 app,这个 app 也有一个主页叫 homepage1.html,该 app 的视图函数在加载时,会发现加载的却是第一个 app(mytest)的主页,这是为什么?查询官方文档得到答案:
模板的加载方式有数种,最常用的两种是:
django.template.loaders.filesystem.Loader
django.template.loaders.app_directories.Loader
是可受控制的,配置方式在 settings.py 中的 TAMPLATE配置项中:
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(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',
],
},
},
]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
其中 OPTIONS 中有一配置项为:’loaders’,上述代码中是没有的,因为是缺省的,如果不设置,则为
'loaders': [
'django.template.loaders.filesystem.Loader',
]
- 1
- 2
- 3
即为第一种加载方式
Loads templates from the filesystem, according to DIRS.
This loader is enabled by default. However it won’t find any templates
until you set DIRS to a non-empty list。这种加载方式会根据 DIRS 配置的路径从文件系统中加载模板文件。
这种加载方式是缺省的方式,但 DIRS 必须为一个有效的路径。
这个时候我们可以故意设置一个不存在的模板让加载器去寻找,然后就可以看出他的加载路径:
Django tried loading these templates, in this order:
Using engine django:
django.template.loaders.filesystem.Loader: F:\python\work\mysite\templates\homepage1.html (Source does not exist)
- 1
- 2
- 3
- 4
mysite 是整个项目的名称,可以看出加载方式就是直接寻找我们设置的路径 F:\python\work\mysite\templates 中是否有模板,不会寻找其他路径。
再看第二种方式 django.template.loaders.app_directories.Loader:
启动第二种方式需配置:
'APP_DIRS':False,
'loaders': [
' django.template.loaders.app_directories.Loader',
]
- 1
- 2
- 3
- 4
官方原文(原文略长,直接中文):
这种方式会顺序遍历 INSTALLED_APPS 中加载的每一个 app 目录中的子目录 templates。比如 app 加载如下:
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'blog',
'mytest',
]
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
则模板的寻找方式如下:
Using engine django:
django.template.loaders.app_directories.Loader: C:\Program Files\Python35\lib\site-packages\django\contrib\admin\templates\homepage1.html (Source does not exist)
django.template.loaders.app_directories.Loader: C:\Program Files\Python35\lib\site-packages\django\contrib\auth\templates\homepage1.html (Source does not exist)
django.template.loaders.app_directories.Loader: F:\python\work\mysite\blog\templates\homepage1.html (Source does not exist)
django.template.loaders.app_directories.Loader: F:\python\work\mysite\mytest\templates\homepage1.html (Source does not exist)
- 1
- 2
- 3
- 4
- 5
可以看到是按照 app 的顺序寻找的。但这种方式有弊端:
同名模板在不同 app 中时,只会加载第一个,其他的会被忽略。
这就是今天的问题,要怎么定位不同 app 中的同名模板呢?
一种有效的方式就是:
使用第一种加载方式(django.template.loaders.filesystem.Loader),
在指定的加载目录(通常是工程根目录的 templates)中对不同的 app 的模板进行分类,即:
mysite------
-app1
-app2
-templates----
-app1-----
-home.html
-app2-----
-home.html
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
同时在视图函数中加载模板时写上具体的路径
#app1 views.py
t = loader.get_template("app1/home.html")
#app2 views.py
t = loader.get_template("app2/home.html")