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