Fixed #22756 -- Added view name to technical 404 template if Http404 is raised.

Thanks Keryn Knight for the suggestion.
This commit is contained in:
Julia Matsieva 2014-06-16 00:39:18 -07:00 committed by Tim Graham
parent 0b5bafe993
commit 29c1151a55
5 changed files with 53 additions and 2 deletions

View File

@ -430,6 +430,7 @@ answer newbie questions, and generally made Django that much better:
Orestis Markou <orestis@orestis.gr> Orestis Markou <orestis@orestis.gr>
Andrés Torres Marroquín <andres.torres.marroquin@gmail.com> Andrés Torres Marroquín <andres.torres.marroquin@gmail.com>
Pablo Martín <goinnn@gmail.com> Pablo Martín <goinnn@gmail.com>
Julia Matsieva <julia.matsieva@gmail.com>
Takashi Matsuo <matsuo.takashi@gmail.com> Takashi Matsuo <matsuo.takashi@gmail.com>
Zlatko Mašek <zlatko.masek@gmail.com> Zlatko Mašek <zlatko.masek@gmail.com>
Yasushi Masuda <whosaysni@gmail.com> Yasushi Masuda <whosaysni@gmail.com>

View File

@ -7,6 +7,7 @@ import sys
import types import types
from django.conf import settings from django.conf import settings
from django.core.urlresolvers import resolve, Resolver404
from django.http import (HttpResponse, HttpResponseNotFound, HttpRequest, from django.http import (HttpResponse, HttpResponseNotFound, HttpRequest,
build_request_repr) build_request_repr)
from django.template import Template, Context, TemplateDoesNotExist from django.template import Template, Context, TemplateDoesNotExist
@ -496,6 +497,23 @@ def technical_404_response(request, exception):
if isinstance(urlconf, types.ModuleType): if isinstance(urlconf, types.ModuleType):
urlconf = urlconf.__name__ urlconf = urlconf.__name__
caller = ''
try:
resolver_match = resolve(request.path)
except Resolver404:
pass
else:
obj = resolver_match.func
if hasattr(obj, '__name__'):
caller = obj.__name__
elif hasattr(obj, '__class__') and hasattr(obj.__class__, '__name__'):
caller = obj.__class__.__name__
if hasattr(obj, '__module__'):
module = obj.__module__
caller = '%s.%s' % (module, caller)
t = Template(TECHNICAL_404_TEMPLATE, name='Technical 404 template') t = Template(TECHNICAL_404_TEMPLATE, name='Technical 404 template')
c = Context({ c = Context({
'urlconf': urlconf, 'urlconf': urlconf,
@ -505,6 +523,7 @@ def technical_404_response(request, exception):
'reason': force_bytes(exception, errors='replace'), 'reason': force_bytes(exception, errors='replace'),
'request': request, 'request': request,
'settings': get_safe_settings(), 'settings': get_safe_settings(),
'raising_view_name': caller,
}) })
return HttpResponseNotFound(t.render(c), content_type='text/html') return HttpResponseNotFound(t.render(c), content_type='text/html')
@ -1093,6 +1112,12 @@ TECHNICAL_404_TEMPLATE = """
<th>Request URL:</th> <th>Request URL:</th>
<td>{{ request.build_absolute_uri|escape }}</td> <td>{{ request.build_absolute_uri|escape }}</td>
</tr> </tr>
{% if raising_view_name %}
<tr>
<th>Raised by:</th>
<td>{{ raising_view_name }}</td>
</tr>
{% endif %}
</table> </table>
</div> </div>
<div id="info"> <div id="info">

View File

@ -72,8 +72,19 @@ class DebugViewTests(TestCase):
def test_404_not_in_urls(self): def test_404_not_in_urls(self):
response = self.client.get('/not-in-urls') response = self.client.get('/not-in-urls')
self.assertNotContains(response, "Raised by:", status_code=404)
self.assertContains(response, "<code>not-in-urls</code>, didn't match", status_code=404) self.assertContains(response, "<code>not-in-urls</code>, didn't match", status_code=404)
def test_technical_404(self):
response = self.client.get('/views/technical404/')
self.assertContains(response, "Raised by:", status_code=404)
self.assertContains(response, "view_tests.views.technical404", status_code=404)
def test_classbased_technical_404(self):
response = self.client.get('/views/classbased404/')
self.assertContains(response, "Raised by:", status_code=404)
self.assertContains(response, "view_tests.views.Http404View", status_code=404)
def test_view_exceptions(self): def test_view_exceptions(self):
for n in range(len(except_args)): for n in range(len(except_args)):
self.assertRaises(BrokenException, self.client.get, self.assertRaises(BrokenException, self.client.get,

View File

@ -57,6 +57,9 @@ urlpatterns = [
url(r'raises404/$', views.raises404), url(r'raises404/$', views.raises404),
url(r'raises500/$', views.raises500), url(r'raises500/$', views.raises500),
url(r'technical404/$', views.technical404, name="my404"),
url(r'classbased404/$', views.Http404View.as_view()),
# i18n views # i18n views
url(r'^i18n/', include('django.conf.urls.i18n')), url(r'^i18n/', include('django.conf.urls.i18n')),
url(r'^jsi18n/$', i18n.javascript_catalog, js_info_dict), url(r'^jsi18n/$', i18n.javascript_catalog, js_info_dict),

View File

@ -7,7 +7,7 @@ import sys
from django.core.exceptions import PermissionDenied, SuspiciousOperation from django.core.exceptions import PermissionDenied, SuspiciousOperation
from django.core.urlresolvers import get_resolver from django.core.urlresolvers import get_resolver
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse from django.http import HttpResponse, HttpResponseRedirect, JsonResponse, Http404
from django.shortcuts import render_to_response, render from django.shortcuts import render_to_response, render
from django.template import Context, RequestContext, TemplateDoesNotExist from django.template import Context, RequestContext, TemplateDoesNotExist
from django.views.debug import technical_500_response, SafeExceptionReporterFilter from django.views.debug import technical_500_response, SafeExceptionReporterFilter
@ -16,6 +16,8 @@ from django.views.decorators.debug import (sensitive_post_parameters,
from django.utils._os import upath from django.utils._os import upath
from django.utils.log import getLogger from django.utils.log import getLogger
from django.views.generic import View
from . import BrokenException, except_args from . import BrokenException, except_args
dirs = (os.path.join(os.path.dirname(upath(__file__)), 'other_templates'),) dirs = (os.path.join(os.path.dirname(upath(__file__)), 'other_templates'),)
@ -60,6 +62,15 @@ def raises404(request):
resolver.resolve('/not-in-urls') resolver.resolve('/not-in-urls')
def technical404(request):
raise Http404("Testing technical 404.")
class Http404View(View):
def get(self, request):
raise Http404("Testing class-based technical 404.")
def redirect(request): def redirect(request):
""" """
Forces an HTTP redirect. Forces an HTTP redirect.