diff options
| author | Jacob Walls <jacobtylerwalls@gmail.com> | 2025-09-18 12:53:24 -0400 |
|---|---|---|
| committer | Sarah Boyce <42296566+sarahboyce@users.noreply.github.com> | 2025-09-26 14:06:39 +0200 |
| commit | 7894776bc99e42f20e0919fc9027e6db542957d5 (patch) | |
| tree | e83b60f583d979fe0c7014f6ab2ec5e049972e5d | |
| parent | 46bd92274c57fd6f138c067562696092732cec59 (diff) | |
Refs #28526 -- Provided URLResolver namespace in technical 404 template.
This avoids looking up the nonexistent "name" attribute on URLResolver,
which logs verbosely.
| -rw-r--r-- | django/views/debug.py | 19 | ||||
| -rw-r--r-- | django/views/templates/technical_404.html | 8 | ||||
| -rw-r--r-- | tests/view_tests/tests/test_debug.py | 10 |
3 files changed, 31 insertions, 6 deletions
diff --git a/django/views/debug.py b/django/views/debug.py index 5a1b4aee91..f7e141d1c6 100644 --- a/django/views/debug.py +++ b/django/views/debug.py @@ -11,7 +11,7 @@ from django.conf import settings from django.http import Http404, HttpResponse, HttpResponseNotFound from django.template import Context, Engine, TemplateDoesNotExist from django.template.defaultfilters import pprint -from django.urls import resolve +from django.urls import URLResolver, resolve from django.utils import timezone from django.utils.datastructures import MultiValueDict from django.utils.encoding import force_str @@ -635,6 +635,20 @@ def technical_404_response(request, exception): ): return default_urlconf(request) + patterns_with_debug_info = [] + for urlpattern in tried or (): + patterns = [] + for inner_pattern in urlpattern: + wrapper = {"tried": inner_pattern} + if isinstance(inner_pattern, URLResolver): + wrapper["debug_key"] = "namespace" + wrapper["debug_val"] = inner_pattern.namespace + else: + wrapper["debug_key"] = "name" + wrapper["debug_val"] = inner_pattern.name + patterns.append(wrapper) + patterns_with_debug_info.append(patterns) + urlconf = getattr(request, "urlconf", settings.ROOT_URLCONF) if isinstance(urlconf, types.ModuleType): urlconf = urlconf.__name__ @@ -647,7 +661,8 @@ def technical_404_response(request, exception): "urlconf": urlconf, "root_urlconf": settings.ROOT_URLCONF, "request_path": error_url, - "urlpatterns": tried, + "urlpatterns": tried, # Unused, left for compatibility. + "urlpatterns_debug": patterns_with_debug_info, "resolved": resolved, "reason": str(exception), "request": request, diff --git a/django/views/templates/technical_404.html b/django/views/templates/technical_404.html index f8d4e92c08..73abb22af4 100644 --- a/django/views/templates/technical_404.html +++ b/django/views/templates/technical_404.html @@ -46,18 +46,18 @@ </header> <main id="info"> - {% if urlpatterns %} + {% if urlpatterns_debug %} <p> Using the URLconf defined in <code>{{ urlconf }}</code>, Django tried these URL patterns, in this order: </p> <ol> - {% for pattern in urlpatterns %} + {% for pattern in urlpatterns_debug %} <li> {% for pat in pattern %} <code> - {{ pat.pattern }} - {% if forloop.last and pat.name %}[name='{{ pat.name }}']{% endif %} + {{ pat.tried.pattern }} + {% if forloop.last and pat.debug_val %}[{{ pat.debug_key }}='{{ pat.debug_val }}']{% endif %} </code> {% endfor %} </li> diff --git a/tests/view_tests/tests/test_debug.py b/tests/view_tests/tests/test_debug.py index 8e36ab7eb1..439faff84e 100644 --- a/tests/view_tests/tests/test_debug.py +++ b/tests/view_tests/tests/test_debug.py @@ -423,6 +423,16 @@ class DebugViewTests(SimpleTestCase): response, "<h1>The install worked successfully! Congratulations!</h1>" ) + @override_settings(ROOT_URLCONF="view_tests.default_urls") + def test_default_urlconf_technical_404(self): + response = self.client.get("/favicon.ico") + self.assertContains( + response, + "<code>\nadmin/\n[namespace='admin']\n</code>", + status_code=404, + html=True, + ) + @override_settings(ROOT_URLCONF="view_tests.regression_21530_urls") def test_regression_21530(self): """ |
