问题描述:Django项目中,多个app下有同名DTL模板,引用模板不正确的问题。
环境:
>python --version
Python 3.7.1
>python -m django --version
2.1.4
目录结构(部分文件已省略):
│ manage.py
│
├─apps
│ │ __init__.py
│ │
│ ├─app03
│ │ │ urls.py
│ │ │ views.py
│ │ │ __init__.py
│ │ │
│ │ ├─templates
│ │ │ index.html
│ │ └─...
│ │
│ ├─app04
│ │ │ urls.py
│ │ │ views.py
│ │ │ __init__.py
│ │ │
│ │ ├─templates
│ │ │ index.html
│ │ └─...
│ └─...
│
├─djangostart
│ │ settings.py
│ │ urls.py
│ │ wsgi.py
│ │ __init__.py
│ │
│ └─...
│
└─templates
...
djangostart/urls.py
文件中配置:
# namespace是实例命名空间,在这里去掉也不影响;
# 但注意使用实例命名空间之前一定要在app的`urls.py`文件中配置应用(app)命名空间。
path('app03/', include('apps.app03.urls', namespace='app03')),
path('app04/', include('apps.app04.urls')),
apps/app04/urls.py
文件中配置:
path('', views.index),
apps/app04/views.py
文件中:
def index(request):
context = {
'value': 'onefine',
}
return render(request, 'index.html', context=context)
apps/app04/templates/index.html
中:
{% load self_filter %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>app04-index.html</title>
</head>
<body>
{{ value|my_filter:"hello" }}
</body>
</html>
djangostart/settings.py
中配置:
...
INSTALLED_APPS = [
...
'apps.app03',
'apps.app04',
# 我尝试过交互这两个app的安装顺序,结果是先安装的访问引用的模板正常,而后按照的访问就不正常。
]
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',
],
},
},
]
...
运行服务,访问 http://127.0.0.1:8000/app04/
但引用的却是apps/app03/templates/index.html
的DTL模板。
按照我的理解,DTL模板的查找顺序应该是:比如代码render('index.html')
。先会在DIRS
这个列表中依次查找路径下有没有这个模板,如果有就返回。如果DIRS
列表中所有的路径都没有找到,那么会先检查当前这个视图所处的app
是否已经安装,如果已经安装了,那么就先在当前这个app
下的templates
文件夹中查找模板,如果没有找到,那么会在其他已经安装了的app
中查找。如果所有路径下都没有找到,那么会抛出一个TemplateDoesNotExist
异常。
我的代码apps/app04/templates/
中有index.html
模板,但为什么引用的却是apps/app03/templates/
下面的模板。
百思不得其解… 虽然已经找到下面的解决方法,但还是不知道为什么这样,先记录一下。
解决办法:
1、在app下新建文件夹templates
,在templates
里面建立app同名文件夹,再放入DTL模板。
2、引用模版的时候,采用<appname>/index.html
这种方式。
完成之后目录结构(部分文件已省略):
│ manage.py
│
├─apps
│ │ __init__.py
│ │
│ ├─app03
│ │ │ urls.py
│ │ │ views.py
│ │ │ __init__.py
│ │ │
│ │ ├─templates
│ │ │ └─app03
│ │ │ index.html
│ │ │
│ │ └─...
│ │
│ ├─app04
│ │ │ urls.py
│ │ │ views.py
│ │ │ __init__.py
│ │ │
│ │ ├─templates
│ │ │ └─app04
│ │ │ index.html
│ │ └─...
│ │
│ └─...
│
├─djangostart
│ │ settings.py
│ │ urls.py
│ │ wsgi.py
│ │ __init__.py
│ │
│ └─...
│
└─templates
...
重新运行服务,访问 http://127.0.0.1:8000/app04/
现在倒是正常了。
PS: 如果有大佬知道原因,希望不吝赐教!
参考:
Django 多 app 同名 模版 引用: https://blog.csdn.net/u013205877/article/details/77278777?utm_source=blogxgwz4
注:在被参考的博客中已经找到些思路,但是还不是特别明确,比如里面提到修改Django模板的载入模式:APP_DIRS
的值设置为True
,同时将DIRS
设置为空,表示启用django.template.loaders.app_directories.Loader,DIRS
——它会从app
对应的templates
目录中查找要渲染的模板文件,即使找不到也不去其他app里面找。
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',
],
},
},
]
运行服务,访问: http://127.0.0.1:8000/app04/
还是不正常!