Made debug views not crash when there isn't a default template engine.
This commit is contained in:
parent
79deb6a071
commit
6b5113ec94
|
@ -7,12 +7,12 @@ import sys
|
||||||
import types
|
import types
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
|
from django.core.exceptions import ImproperlyConfigured
|
||||||
from django.core.urlresolvers import resolve, Resolver404
|
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 Context, Engine, TemplateDoesNotExist
|
||||||
from django.template.defaultfilters import force_escape, pprint
|
from django.template.defaultfilters import force_escape, pprint
|
||||||
from django.template.engine import Engine
|
|
||||||
from django.utils.datastructures import MultiValueDict
|
from django.utils.datastructures import MultiValueDict
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
from django.utils.encoding import force_bytes, smart_text
|
from django.utils.encoding import force_bytes, smart_text
|
||||||
|
@ -21,6 +21,11 @@ from django.utils.module_loading import import_string
|
||||||
from django.utils import six
|
from django.utils import six
|
||||||
from django.utils.translation import ugettext as _
|
from django.utils.translation import ugettext as _
|
||||||
|
|
||||||
|
|
||||||
|
# Minimal Django templates engine to render the error templates
|
||||||
|
# regardless of the project's TEMPLATES setting.
|
||||||
|
DEBUG_ENGINE = Engine(debug=True)
|
||||||
|
|
||||||
HIDDEN_SETTINGS = re.compile('API|TOKEN|KEY|SECRET|PASS|SIGNATURE')
|
HIDDEN_SETTINGS = re.compile('API|TOKEN|KEY|SECRET|PASS|SIGNATURE')
|
||||||
|
|
||||||
CLEANSED_SUBSTITUTE = '********************'
|
CLEANSED_SUBSTITUTE = '********************'
|
||||||
|
@ -275,19 +280,27 @@ class ExceptionReporter(object):
|
||||||
|
|
||||||
def get_traceback_data(self):
|
def get_traceback_data(self):
|
||||||
"""Return a dictionary containing traceback information."""
|
"""Return a dictionary containing traceback information."""
|
||||||
|
try:
|
||||||
|
default_template_engine = Engine.get_default()
|
||||||
|
except ImproperlyConfigured:
|
||||||
|
default_template_engine = None
|
||||||
|
|
||||||
# TODO: handle multiple template engines.
|
# TODO: add support for multiple template engines (#24120).
|
||||||
template_engine = Engine.get_default()
|
# TemplateDoesNotExist should carry all the information.
|
||||||
|
# Replaying the search process isn't a good design.
|
||||||
if self.exc_type and issubclass(self.exc_type, TemplateDoesNotExist):
|
if self.exc_type and issubclass(self.exc_type, TemplateDoesNotExist):
|
||||||
|
if default_template_engine is None:
|
||||||
|
template_loaders = []
|
||||||
|
else:
|
||||||
self.template_does_not_exist = True
|
self.template_does_not_exist = True
|
||||||
self.loader_debug_info = []
|
self.loader_debug_info = []
|
||||||
# If Django fails in get_template_loaders, provide an empty list
|
# If Django fails in get_template_loaders, provide an empty list
|
||||||
# for the following loop to not fail.
|
# for the following loop to not fail.
|
||||||
try:
|
try:
|
||||||
template_loaders = template_engine.template_loaders
|
template_loaders = default_template_engine.template_loaders
|
||||||
except Exception:
|
except Exception:
|
||||||
template_loaders = []
|
template_loaders = []
|
||||||
|
|
||||||
for loader in template_loaders:
|
for loader in template_loaders:
|
||||||
try:
|
try:
|
||||||
source_list_func = loader.get_template_sources
|
source_list_func = loader.get_template_sources
|
||||||
|
@ -304,8 +317,11 @@ class ExceptionReporter(object):
|
||||||
'loader': loader_name,
|
'loader': loader_name,
|
||||||
'templates': template_list,
|
'templates': template_list,
|
||||||
})
|
})
|
||||||
if (template_engine.debug and
|
|
||||||
hasattr(self.exc_value, 'django_template_source')):
|
# TODO: add support for multiple template engines (#24119).
|
||||||
|
if (default_template_engine is not None
|
||||||
|
and default_template_engine.debug
|
||||||
|
and hasattr(self.exc_value, 'django_template_source')):
|
||||||
self.get_template_exception_info()
|
self.get_template_exception_info()
|
||||||
|
|
||||||
frames = self.get_traceback_frames()
|
frames = self.get_traceback_frames()
|
||||||
|
@ -362,13 +378,13 @@ class ExceptionReporter(object):
|
||||||
|
|
||||||
def get_traceback_html(self):
|
def get_traceback_html(self):
|
||||||
"Return HTML version of debug 500 HTTP error page."
|
"Return HTML version of debug 500 HTTP error page."
|
||||||
t = Template(TECHNICAL_500_TEMPLATE, name='Technical 500 template')
|
t = DEBUG_ENGINE.from_string(TECHNICAL_500_TEMPLATE)
|
||||||
c = Context(self.get_traceback_data(), use_l10n=False)
|
c = Context(self.get_traceback_data(), use_l10n=False)
|
||||||
return t.render(c)
|
return t.render(c)
|
||||||
|
|
||||||
def get_traceback_text(self):
|
def get_traceback_text(self):
|
||||||
"Return plain text version of debug 500 HTTP error page."
|
"Return plain text version of debug 500 HTTP error page."
|
||||||
t = Template(TECHNICAL_500_TEXT_TEMPLATE, name='Technical 500 template')
|
t = DEBUG_ENGINE.from_string(TECHNICAL_500_TEXT_TEMPLATE)
|
||||||
c = Context(self.get_traceback_data(), autoescape=False, use_l10n=False)
|
c = Context(self.get_traceback_data(), autoescape=False, use_l10n=False)
|
||||||
return t.render(c)
|
return t.render(c)
|
||||||
|
|
||||||
|
@ -545,7 +561,7 @@ def technical_404_response(request, exception):
|
||||||
module = obj.__module__
|
module = obj.__module__
|
||||||
caller = '%s.%s' % (module, caller)
|
caller = '%s.%s' % (module, caller)
|
||||||
|
|
||||||
t = Template(TECHNICAL_404_TEMPLATE, name='Technical 404 template')
|
t = DEBUG_ENGINE.from_string(TECHNICAL_404_TEMPLATE)
|
||||||
c = Context({
|
c = Context({
|
||||||
'urlconf': urlconf,
|
'urlconf': urlconf,
|
||||||
'root_urlconf': settings.ROOT_URLCONF,
|
'root_urlconf': settings.ROOT_URLCONF,
|
||||||
|
@ -561,8 +577,7 @@ def technical_404_response(request, exception):
|
||||||
|
|
||||||
def default_urlconf(request):
|
def default_urlconf(request):
|
||||||
"Create an empty URLconf 404 error response."
|
"Create an empty URLconf 404 error response."
|
||||||
t = Template(DEFAULT_URLCONF_TEMPLATE, name='Default URLconf template')
|
t = DEBUG_ENGINE.from_string(DEFAULT_URLCONF_TEMPLATE)
|
||||||
|
|
||||||
c = Context({
|
c = Context({
|
||||||
"title": _("Welcome to Django"),
|
"title": _("Welcome to Django"),
|
||||||
"heading": _("It worked!"),
|
"heading": _("It worked!"),
|
||||||
|
|
|
@ -219,6 +219,36 @@ class DebugViewTests(TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@override_settings(
|
||||||
|
DEBUG=True,
|
||||||
|
ROOT_URLCONF="view_tests.urls",
|
||||||
|
# No template directories are configured, so no templates will be found.
|
||||||
|
TEMPLATES=[{
|
||||||
|
'BACKEND': 'django.template.backends.dummy.TemplateStrings',
|
||||||
|
}],
|
||||||
|
)
|
||||||
|
class NonDjangoTemplatesDebugViewTests(TestCase):
|
||||||
|
|
||||||
|
def test_400(self):
|
||||||
|
# Ensure that when DEBUG=True, technical_500_template() is called.
|
||||||
|
response = self.client.get('/raises400/')
|
||||||
|
self.assertContains(response, '<div class="context" id="', status_code=400)
|
||||||
|
|
||||||
|
def test_403(self):
|
||||||
|
response = self.client.get('/raises403/')
|
||||||
|
self.assertContains(response, '<h1>403 Forbidden</h1>', status_code=403)
|
||||||
|
|
||||||
|
def test_404(self):
|
||||||
|
response = self.client.get('/raises404/')
|
||||||
|
self.assertEqual(response.status_code, 404)
|
||||||
|
|
||||||
|
def test_template_not_found_error(self):
|
||||||
|
# Raises a TemplateDoesNotExist exception and shows the debug view.
|
||||||
|
url = reverse('raises_template_does_not_exist', kwargs={"path": "notfound.html"})
|
||||||
|
response = self.client.get(url)
|
||||||
|
self.assertContains(response, '<div class="context" id="', status_code=500)
|
||||||
|
|
||||||
|
|
||||||
class ExceptionReporterTests(TestCase):
|
class ExceptionReporterTests(TestCase):
|
||||||
rf = RequestFactory()
|
rf = RequestFactory()
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue