diff --git a/django/core/handlers/base.py b/django/core/handlers/base.py
index 6a2d0645e0..b34d0e096e 100644
--- a/django/core/handlers/base.py
+++ b/django/core/handlers/base.py
@@ -112,7 +112,10 @@ class BaseHandler(object):
callback, param_dict = resolver.resolve404()
return callback(request, **param_dict)
except:
- return self.handle_uncaught_exception(request, resolver, sys.exc_info())
+ try:
+ return self.handle_uncaught_exception(request, resolver, sys.exc_info())
+ finally:
+ receivers = signals.got_request_exception.send(sender=self.__class__, request=request)
except exceptions.PermissionDenied:
return http.HttpResponseForbidden('
Permission denied
')
except SystemExit:
diff --git a/tests/regressiontests/test_client_regress/bad_templates/404.html b/tests/regressiontests/test_client_regress/bad_templates/404.html
new file mode 100644
index 0000000000..816bcb9e4e
--- /dev/null
+++ b/tests/regressiontests/test_client_regress/bad_templates/404.html
@@ -0,0 +1,3 @@
+{% block foo %}
+
+This template is deliberately bad - we want it to raise an exception when it is used.
diff --git a/tests/regressiontests/test_client_regress/models.py b/tests/regressiontests/test_client_regress/models.py
index 14552b7e63..1bffc7d225 100644
--- a/tests/regressiontests/test_client_regress/models.py
+++ b/tests/regressiontests/test_client_regress/models.py
@@ -1,10 +1,13 @@
"""
Regression tests for the Test Client, especially the customized assertions.
"""
+import os
+from django.conf import settings
from django.test import Client, TestCase
from django.core.urlresolvers import reverse
from django.core.exceptions import SuspiciousOperation
+from django.template import TemplateDoesNotExist, TemplateSyntaxError
class AssertContainsTests(TestCase):
def test_contains(self):
@@ -306,7 +309,32 @@ class ExceptionTests(TestCase):
self.client.get("/test_client_regress/staff_only/")
except SuspiciousOperation:
self.fail("Staff should be able to visit this page")
+
+class TemplateExceptionTests(TestCase):
+ def setUp(self):
+ self.old_templates = settings.TEMPLATE_DIRS
+ settings.TEMPLATE_DIRS = ()
+
+ def tearDown(self):
+ settings.TEMPLATE_DIRS = self.old_templates
+
+ def test_no_404_template(self):
+ "Missing templates are correctly reported by test client"
+ try:
+ response = self.client.get("/no_such_view/")
+ self.fail("Should get error about missing template")
+ except TemplateDoesNotExist:
+ pass
+ def test_bad_404_template(self):
+ "Errors found when rendering 404 error templates are re-raised"
+ settings.TEMPLATE_DIRS = (os.path.join(os.path.dirname(__file__), 'bad_templates'),)
+ try:
+ response = self.client.get("/no_such_view/")
+ self.fail("Should get error about syntax error in template")
+ except TemplateSyntaxError:
+ pass
+
# We need two different tests to check URLconf substitution - one to check
# it was changed, and another one (without self.urls) to check it was reverted on
# teardown. This pair of tests relies upon the alphabetical ordering of test execution.