Django 的 TemplateResponse 在错误的目录中查找模板
Django's TemplateResponse looking in the wrong directory for templates
文件树(粗略示例)
project/
project/
.
.
project_admin/
admin.py
app/
.
.
project_admin/admin.py
from django.contrib import admin
from django.template.response import TemplateResponse
from django.urls import path
class BookrAdmin(admin.AdminSite):
logout_template = 'admin/logout.html'
def profile_view(self, request):
request.current_app = self.name
context = self.each_context(request)
return TemplateResponse(request, 'admin/admin_profile.html', context)
def get_urls(self):
urls = super().get_urls()
url_patterns = [path("admin_profile", self.profile_view)]
return urls + url_patterns
project/settings.py
import os
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
.
.
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',
],
},
},
]
我是个笨蛋,正在更新这个问题。我意识到我最初的 post 是错误的。
这是我的错误。
Request Method: GET
Request URL: http://127.0.0.1:8000/admin/admin_profile
Raised by: django.contrib.admin.sites.catch_all_view
Using the URLconf defined in bookr.urls, Django tried these URL patterns, in this order:
accounts/
accounts/profile/ [name='profile']
admin/ [name='index']
admin/ login/ [name='login']
admin/ logout/ [name='logout']
admin/ password_change/ [name='password_change']
admin/ password_change/done/ [name='password_change_done']
admin/ autocomplete/ [name='autocomplete']
admin/ jsi18n/ [name='jsi18n']
admin/ r/<int:content_type_id>/<path:object_id>/ [name='view_on_site']
admin/ auth/group/
admin/ auth/user/
admin/ reviews/review/
admin/ ^(?P<app_label>auth|reviews)/$ [name='app_list']
admin/ (?P<url>.*)$
The current path, admin/admin_profile, matched the last one.
所以我觉得这与project_admin/admin.py
文件有关。由于 http://127.0.0.1:8000/admin/[this can be anything]
的任何原因,我仍然在匹配路径时遇到相同的错误。我不确定从这里去哪里。我没有得到引用,因为没有什么是失败的。它只是不会由扩展默认 django admin/index.html
.
的 admin_profile.html
加载
---原始编辑的原因---
我认为 TemplateResponse
是从错误的目录中提取的原因是因为我将 pycharm 配置为认为错误的模板目录是我的根模板目录。此问题现已修复。
---回答---
return urls + url_patterns
->return url_patterns + urls
这里发生的事情是您在 get_urls
的结果之后添加了 url 模式。问题是,由于 Django 3.2(此版本中的新版本)在 get_urls
返回的列表末尾有一个 url 模式,它将捕获 all 可能urls 并将它们路由到 catch_all_view
,因此由于它在列表中的模式之前,视图用于您的 url 并且您收到错误。从source code [GitHub]:
可以看出
if self.final_catch_all_view:
urlpatterns.append(re_path(r'(?P<url>.*)$', wrap(self.catch_all_view)))
可以通过在您的管理站点中将 final_catch_all_view
设置为 False
来删除 documentation 中提到的这种行为。但文档还建议不要这样做,因为它可以保护您免受枚举攻击。相反,您应该做的是在列表的 start 添加 url 模式:
class BookrAdmin(admin.AdminSite):
logout_template = 'admin/logout.html'
def profile_view(self, request):
request.current_app = self.name
context = self.each_context(request)
return TemplateResponse(request, 'admin/admin_profile.html', context)
def get_urls(self):
urls = super().get_urls()
url_patterns = [path("admin_profile/", self.profile_view)]
return url_patterns + urls # Keep your patterns first in the list so they don't get caught by the catch all view
文件树(粗略示例)
project/
project/
.
.
project_admin/
admin.py
app/
.
.
project_admin/admin.py
from django.contrib import admin
from django.template.response import TemplateResponse
from django.urls import path
class BookrAdmin(admin.AdminSite):
logout_template = 'admin/logout.html'
def profile_view(self, request):
request.current_app = self.name
context = self.each_context(request)
return TemplateResponse(request, 'admin/admin_profile.html', context)
def get_urls(self):
urls = super().get_urls()
url_patterns = [path("admin_profile", self.profile_view)]
return urls + url_patterns
project/settings.py
import os
from pathlib import Path
BASE_DIR = Path(__file__).resolve().parent.parent
.
.
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',
],
},
},
]
我是个笨蛋,正在更新这个问题。我意识到我最初的 post 是错误的。
这是我的错误。
Request Method: GET
Request URL: http://127.0.0.1:8000/admin/admin_profile
Raised by: django.contrib.admin.sites.catch_all_view
Using the URLconf defined in bookr.urls, Django tried these URL patterns, in this order:
accounts/
accounts/profile/ [name='profile']
admin/ [name='index']
admin/ login/ [name='login']
admin/ logout/ [name='logout']
admin/ password_change/ [name='password_change']
admin/ password_change/done/ [name='password_change_done']
admin/ autocomplete/ [name='autocomplete']
admin/ jsi18n/ [name='jsi18n']
admin/ r/<int:content_type_id>/<path:object_id>/ [name='view_on_site']
admin/ auth/group/
admin/ auth/user/
admin/ reviews/review/
admin/ ^(?P<app_label>auth|reviews)/$ [name='app_list']
admin/ (?P<url>.*)$
The current path, admin/admin_profile, matched the last one.
所以我觉得这与project_admin/admin.py
文件有关。由于 http://127.0.0.1:8000/admin/[this can be anything]
的任何原因,我仍然在匹配路径时遇到相同的错误。我不确定从这里去哪里。我没有得到引用,因为没有什么是失败的。它只是不会由扩展默认 django admin/index.html
.
admin_profile.html
加载
---原始编辑的原因---
我认为 TemplateResponse
是从错误的目录中提取的原因是因为我将 pycharm 配置为认为错误的模板目录是我的根模板目录。此问题现已修复。
---回答---
return urls + url_patterns
->return url_patterns + urls
这里发生的事情是您在 get_urls
的结果之后添加了 url 模式。问题是,由于 Django 3.2(此版本中的新版本)在 get_urls
返回的列表末尾有一个 url 模式,它将捕获 all 可能urls 并将它们路由到 catch_all_view
,因此由于它在列表中的模式之前,视图用于您的 url 并且您收到错误。从source code [GitHub]:
if self.final_catch_all_view: urlpatterns.append(re_path(r'(?P<url>.*)$', wrap(self.catch_all_view)))
可以通过在您的管理站点中将 final_catch_all_view
设置为 False
来删除 documentation 中提到的这种行为。但文档还建议不要这样做,因为它可以保护您免受枚举攻击。相反,您应该做的是在列表的 start 添加 url 模式:
class BookrAdmin(admin.AdminSite):
logout_template = 'admin/logout.html'
def profile_view(self, request):
request.current_app = self.name
context = self.each_context(request)
return TemplateResponse(request, 'admin/admin_profile.html', context)
def get_urls(self):
urls = super().get_urls()
url_patterns = [path("admin_profile/", self.profile_view)]
return url_patterns + urls # Keep your patterns first in the list so they don't get caught by the catch all view