Fixed #6412 -- More details if a template file cannot be loaded
Report more details about template files in loader postmortem.
This commit is contained in:
parent
fd961941cc
commit
61a8de6f4f
|
@ -218,6 +218,15 @@ class ExceptionReporter(object):
|
||||||
self.exc_value = Exception('Deprecated String Exception: %r' % self.exc_type)
|
self.exc_value = Exception('Deprecated String Exception: %r' % self.exc_type)
|
||||||
self.exc_type = type(self.exc_value)
|
self.exc_type = type(self.exc_value)
|
||||||
|
|
||||||
|
def format_path_status(self, path):
|
||||||
|
if not os.path.exists(path):
|
||||||
|
return "File does not exist"
|
||||||
|
if not os.path.isfile(path):
|
||||||
|
return "Not a file"
|
||||||
|
if not os.access(path, os.R_OK):
|
||||||
|
return "File is not readable"
|
||||||
|
return "File exists"
|
||||||
|
|
||||||
def get_traceback_data(self):
|
def get_traceback_data(self):
|
||||||
"Return a Context instance containing traceback information."
|
"Return a Context instance containing traceback information."
|
||||||
|
|
||||||
|
@ -230,8 +239,10 @@ class ExceptionReporter(object):
|
||||||
source_list_func = loader.get_template_sources
|
source_list_func = loader.get_template_sources
|
||||||
# NOTE: This assumes exc_value is the name of the template that
|
# NOTE: This assumes exc_value is the name of the template that
|
||||||
# the loader attempted to load.
|
# the loader attempted to load.
|
||||||
template_list = [{'name': t, 'exists': os.path.exists(t)} \
|
template_list = [{
|
||||||
for t in source_list_func(str(self.exc_value))]
|
'name': t,
|
||||||
|
'status': self.format_path_status(t),
|
||||||
|
} for t in source_list_func(str(self.exc_value))]
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
template_list = []
|
template_list = []
|
||||||
loader_name = loader.__module__ + '.' + loader.__class__.__name__
|
loader_name = loader.__module__ + '.' + loader.__class__.__name__
|
||||||
|
@ -650,7 +661,9 @@ TECHNICAL_500_TEMPLATE = """
|
||||||
<ul>
|
<ul>
|
||||||
{% for loader in loader_debug_info %}
|
{% for loader in loader_debug_info %}
|
||||||
<li>Using loader <code>{{ loader.loader }}</code>:
|
<li>Using loader <code>{{ loader.loader }}</code>:
|
||||||
<ul>{% for t in loader.templates %}<li><code>{{ t.name }}</code> (File {% if t.exists %}exists{% else %}does not exist{% endif %})</li>{% endfor %}</ul>
|
<ul>
|
||||||
|
{% for t in loader.templates %}<li><code>{{ t.name }}</code> ({{ t.status }})</li>{% endfor %}
|
||||||
|
</ul>
|
||||||
</li>
|
</li>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</ul>
|
||||||
|
@ -753,7 +766,7 @@ Installed Middleware:
|
||||||
{% if template_does_not_exist %}Template Loader Error:
|
{% if template_does_not_exist %}Template Loader Error:
|
||||||
{% if loader_debug_info %}Django tried loading these templates, in this order:
|
{% if loader_debug_info %}Django tried loading these templates, in this order:
|
||||||
{% for loader in loader_debug_info %}Using loader {{ loader.loader }}:
|
{% for loader in loader_debug_info %}Using loader {{ loader.loader }}:
|
||||||
{% for t in loader.templates %}{{ t.name }} (File {% if t.exists %}exists{% else %}does not exist{% endif %})
|
{% for t in loader.templates %}{{ t.name }} ({{ t.status }})
|
||||||
{% endfor %}{% endfor %}
|
{% endfor %}{% endfor %}
|
||||||
{% else %}Django couldn't find any templates because your TEMPLATE_LOADERS setting is empty!
|
{% else %}Django couldn't find any templates because your TEMPLATE_LOADERS setting is empty!
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@ -943,7 +956,7 @@ Installed Middleware:
|
||||||
{% if template_does_not_exist %}Template loader Error:
|
{% if template_does_not_exist %}Template loader Error:
|
||||||
{% if loader_debug_info %}Django tried loading these templates, in this order:
|
{% if loader_debug_info %}Django tried loading these templates, in this order:
|
||||||
{% for loader in loader_debug_info %}Using loader {{ loader.loader }}:
|
{% for loader in loader_debug_info %}Using loader {{ loader.loader }}:
|
||||||
{% for t in loader.templates %}{{ t.name }} (File {% if t.exists %}exists{% else %}does not exist{% endif %})
|
{% for t in loader.templates %}{{ t.name }} ({{ t.status }})
|
||||||
{% endfor %}{% endfor %}
|
{% endfor %}{% endfor %}
|
||||||
{% else %}Django couldn't find any templates because your TEMPLATE_LOADERS setting is empty!
|
{% else %}Django couldn't find any templates because your TEMPLATE_LOADERS setting is empty!
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -5,8 +5,9 @@ from __future__ import absolute_import, unicode_literals
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
import os
|
import os
|
||||||
|
import shutil
|
||||||
import sys
|
import sys
|
||||||
import tempfile
|
from tempfile import NamedTemporaryFile, mkdtemp, mkstemp
|
||||||
|
|
||||||
from django.core import mail
|
from django.core import mail
|
||||||
from django.core.files.uploadedfile import SimpleUploadedFile
|
from django.core.files.uploadedfile import SimpleUploadedFile
|
||||||
|
@ -21,6 +22,7 @@ from .. import BrokenException, except_args
|
||||||
from ..views import (sensitive_view, non_sensitive_view, paranoid_view,
|
from ..views import (sensitive_view, non_sensitive_view, paranoid_view,
|
||||||
custom_exception_reporter_filter_view, sensitive_method_view,
|
custom_exception_reporter_filter_view, sensitive_method_view,
|
||||||
sensitive_args_function_caller, sensitive_kwargs_function_caller)
|
sensitive_args_function_caller, sensitive_kwargs_function_caller)
|
||||||
|
from django.utils.unittest import skipIf
|
||||||
|
|
||||||
|
|
||||||
@override_settings(DEBUG=True, TEMPLATE_DEBUG=True)
|
@override_settings(DEBUG=True, TEMPLATE_DEBUG=True)
|
||||||
|
@ -78,9 +80,38 @@ class DebugViewTests(TestCase):
|
||||||
raising_loc)
|
raising_loc)
|
||||||
|
|
||||||
def test_template_loader_postmortem(self):
|
def test_template_loader_postmortem(self):
|
||||||
response = self.client.get(reverse('raises_template_does_not_exist'))
|
"""Tests for not existing file"""
|
||||||
template_path = os.path.join('templates', 'i_dont_exist.html')
|
template_name = "notfound.html"
|
||||||
self.assertContains(response, template_path, status_code=500)
|
with NamedTemporaryFile(prefix=template_name) as tempfile:
|
||||||
|
tempdir = os.path.dirname(tempfile.name)
|
||||||
|
template_path = os.path.join(tempdir, template_name)
|
||||||
|
with override_settings(TEMPLATE_DIRS=(tempdir,)):
|
||||||
|
response = self.client.get(reverse('raises_template_does_not_exist', kwargs={"path": template_name}))
|
||||||
|
self.assertContains(response, "%s (File does not exist)" % template_path, status_code=500, count=1)
|
||||||
|
|
||||||
|
@skipIf(sys.platform == "win32", "Python on Windows doesn't have working os.chmod() and os.access().")
|
||||||
|
def test_template_loader_postmortem_notreadable(self):
|
||||||
|
"""Tests for not readable file"""
|
||||||
|
with NamedTemporaryFile() as tempfile:
|
||||||
|
template_name = tempfile.name
|
||||||
|
tempdir = os.path.dirname(tempfile.name)
|
||||||
|
template_path = os.path.join(tempdir, template_name)
|
||||||
|
os.chmod(template_path, 0o0222)
|
||||||
|
with override_settings(TEMPLATE_DIRS=(tempdir,)):
|
||||||
|
response = self.client.get(reverse('raises_template_does_not_exist', kwargs={"path": template_name}))
|
||||||
|
self.assertContains(response, "%s (File is not readable)" % template_path, status_code=500, count=1)
|
||||||
|
|
||||||
|
def test_template_loader_postmortem_notafile(self):
|
||||||
|
"""Tests for not being a file"""
|
||||||
|
try:
|
||||||
|
template_path = mkdtemp()
|
||||||
|
template_name = os.path.basename(template_path)
|
||||||
|
tempdir = os.path.dirname(template_path)
|
||||||
|
with override_settings(TEMPLATE_DIRS=(tempdir,)):
|
||||||
|
response = self.client.get(reverse('raises_template_does_not_exist', kwargs={"path": template_name}))
|
||||||
|
self.assertContains(response, "%s (Not a file)" % template_path, status_code=500, count=1)
|
||||||
|
finally:
|
||||||
|
shutil.rmtree(template_path)
|
||||||
|
|
||||||
|
|
||||||
class ExceptionReporterTests(TestCase):
|
class ExceptionReporterTests(TestCase):
|
||||||
|
@ -129,7 +160,7 @@ class ExceptionReporterTests(TestCase):
|
||||||
reporter = ExceptionReporter(None, None, None, None)
|
reporter = ExceptionReporter(None, None, None, None)
|
||||||
|
|
||||||
for newline in ['\n', '\r\n', '\r']:
|
for newline in ['\n', '\r\n', '\r']:
|
||||||
fd,filename = tempfile.mkstemp(text = False)
|
fd, filename = mkstemp(text=False)
|
||||||
os.write(fd, force_bytes(newline.join(LINES)+newline))
|
os.write(fd, force_bytes(newline.join(LINES)+newline))
|
||||||
os.close(fd)
|
os.close(fd)
|
||||||
|
|
||||||
|
|
|
@ -66,5 +66,5 @@ urlpatterns = patterns('',
|
||||||
urlpatterns += patterns('view_tests.views',
|
urlpatterns += patterns('view_tests.views',
|
||||||
url(r'view_exception/(?P<n>\d+)/$', 'view_exception', name='view_exception'),
|
url(r'view_exception/(?P<n>\d+)/$', 'view_exception', name='view_exception'),
|
||||||
url(r'template_exception/(?P<n>\d+)/$', 'template_exception', name='template_exception'),
|
url(r'template_exception/(?P<n>\d+)/$', 'template_exception', name='template_exception'),
|
||||||
url(r'^raises_template_does_not_exist/$', 'raises_template_does_not_exist', name='raises_template_does_not_exist'),
|
url(r'^raises_template_does_not_exist/(?P<path>.+)$', 'raises_template_does_not_exist', name='raises_template_does_not_exist'),
|
||||||
)
|
)
|
||||||
|
|
|
@ -112,11 +112,11 @@ def render_view_with_current_app_conflict(request):
|
||||||
'bar': 'BAR',
|
'bar': 'BAR',
|
||||||
}, current_app="foobar_app", context_instance=RequestContext(request))
|
}, current_app="foobar_app", context_instance=RequestContext(request))
|
||||||
|
|
||||||
def raises_template_does_not_exist(request):
|
def raises_template_does_not_exist(request, path='i_dont_exist.html'):
|
||||||
# We need to inspect the HTML generated by the fancy 500 debug view but
|
# We need to inspect the HTML generated by the fancy 500 debug view but
|
||||||
# the test client ignores it, so we send it explicitly.
|
# the test client ignores it, so we send it explicitly.
|
||||||
try:
|
try:
|
||||||
return render_to_response('i_dont_exist.html')
|
return render_to_response(path)
|
||||||
except TemplateDoesNotExist:
|
except TemplateDoesNotExist:
|
||||||
return technical_500_response(request, *sys.exc_info())
|
return technical_500_response(request, *sys.exc_info())
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue