Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions django/views/debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
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
Expand Down Expand Up @@ -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__
Expand All @@ -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,
Expand Down
8 changes: 4 additions & 4 deletions django/views/templates/technical_404.html
Original file line number Diff line number Diff line change
Expand Up @@ -46,18 +46,18 @@ <h1>Page not found <small>(404)</small></h1>
</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>
Expand Down
10 changes: 10 additions & 0 deletions tests/view_tests/tests/test_debug.py
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,16 @@ def test_default_urlconf_script_name(self):
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):
"""
Expand Down
Loading