mirror of
https://github.com/django/django.git
synced 2025-07-06 02:39:12 +00:00
Integrated template errors into new error pages.
git-svn-id: http://code.djangoproject.com/svn/django/branches/new-admin@1299 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
parent
58f4007b55
commit
1e945cb8fa
@ -1,37 +0,0 @@
|
|||||||
{% extends "admin/base_site" %}
|
|
||||||
{% load adminmedia %}
|
|
||||||
{% load i18n %}
|
|
||||||
{% block extrahead%} <link rel="stylesheet" type="text/css" href="{% admin_media_prefix %}css/template_errors.css" /> {%endblock%}
|
|
||||||
{% block content %}
|
|
||||||
<div>
|
|
||||||
<h2>{%trans "Error in Template" %}</h2>
|
|
||||||
<pre>
|
|
||||||
{%blocktrans %}
|
|
||||||
In template {{name}}, error at line {{line}}:
|
|
||||||
{%endblocktrans %}
|
|
||||||
{{message|escape}}
|
|
||||||
{{traceback|escape}}
|
|
||||||
</pre>
|
|
||||||
{%if top%}
|
|
||||||
...
|
|
||||||
{%endif%}
|
|
||||||
|
|
||||||
<table class="source{%if top%} cut-top{%endif%}{%ifnotequal bottom total%} cut-bottom{%endifnotequal%}">
|
|
||||||
{% for source_line in source_lines %}
|
|
||||||
{%ifequal source_line.0 line %}
|
|
||||||
<tr class="error"><td>{{source_line.0}}</td>
|
|
||||||
<td> {{before}}<span class="specific">{{during}}</span>{{after}}</td></tr>
|
|
||||||
{%else%}
|
|
||||||
<tr><td>{{source_line.0}}</td>
|
|
||||||
<td> {{source_line.1}}</td></tr>
|
|
||||||
{%endifequal%}
|
|
||||||
{%endfor%}
|
|
||||||
</table>
|
|
||||||
|
|
||||||
{%ifnotequal bottom total%}
|
|
||||||
...
|
|
||||||
{%endifnotequal%}
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
@ -825,16 +825,11 @@ class DebugNodeList(NodeList):
|
|||||||
if not hasattr(e, 'source'):
|
if not hasattr(e, 'source'):
|
||||||
e.source = node.source
|
e.source = node.source
|
||||||
raise
|
raise
|
||||||
except Exception, e:
|
except Exception:
|
||||||
from traceback import extract_tb, format_list, format_exception_only
|
|
||||||
from sys import exc_info
|
from sys import exc_info
|
||||||
t,v,tb = exc_info()
|
wrapped = TemplateSyntaxError( 'Caught exception whilst rendering' )
|
||||||
frames = extract_tb(tb)
|
|
||||||
frames.pop(0)
|
|
||||||
wrapped = TemplateSyntaxError( 'Caught exception:\n %s'
|
|
||||||
% "".join(format_exception_only(t,v)).replace('\n',''))
|
|
||||||
wrapped.source = node.source
|
wrapped.source = node.source
|
||||||
wrapped.traceback = "".join(format_list(frames))
|
wrapped.exc_info = exc_info()
|
||||||
raise wrapped
|
raise wrapped
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -200,7 +200,6 @@ def dictsort(value, arg):
|
|||||||
Takes a list of dicts, returns that list sorted by the property given in
|
Takes a list of dicts, returns that list sorted by the property given in
|
||||||
the argument.
|
the argument.
|
||||||
"""
|
"""
|
||||||
print "ds:", type(value)
|
|
||||||
decorated = [(resolve_variable('var.' + arg, {'var' : item}), item) for item in value]
|
decorated = [(resolve_variable('var.' + arg, {'var' : item}), item) for item in value]
|
||||||
decorated.sort()
|
decorated.sort()
|
||||||
return [item[1] for item in decorated]
|
return [item[1] for item in decorated]
|
||||||
|
@ -1,56 +0,0 @@
|
|||||||
class TemplateDebugMiddleware(object):
|
|
||||||
def linebreak_iter(self, template_source):
|
|
||||||
import re
|
|
||||||
newline_re = re.compile("^", re.M)
|
|
||||||
for match in newline_re.finditer(template_source):
|
|
||||||
yield match.start()
|
|
||||||
yield len(template_source) + 1
|
|
||||||
|
|
||||||
def process_exception(self, request, exception):
|
|
||||||
from django.core.template.loader import render_to_string
|
|
||||||
from django.utils.html import escape
|
|
||||||
from django.utils.httpwrappers import HttpResponseServerError
|
|
||||||
from django.core.extensions import DjangoContext
|
|
||||||
from itertools import count, izip
|
|
||||||
|
|
||||||
context_lines = 10
|
|
||||||
if hasattr(exception, 'source'):
|
|
||||||
origin, (start, end) = exception.source
|
|
||||||
template_source = origin.reload()
|
|
||||||
|
|
||||||
line = 0
|
|
||||||
upto = 0
|
|
||||||
source_lines = []
|
|
||||||
linebreaks = izip(count(0), self.linebreak_iter(template_source))
|
|
||||||
linebreaks.next() # skip the nothing before initial line start
|
|
||||||
for num, next in linebreaks:
|
|
||||||
if start >= upto and end <= next :
|
|
||||||
line = num
|
|
||||||
before = escape(template_source[upto:start])
|
|
||||||
during = escape(template_source[start:end])
|
|
||||||
after = escape(template_source[end:next - 1])
|
|
||||||
|
|
||||||
source_lines.append( (num, escape(template_source[upto:next - 1])) )
|
|
||||||
upto = next
|
|
||||||
|
|
||||||
total = len(source_lines)
|
|
||||||
|
|
||||||
top = max(0, line - context_lines)
|
|
||||||
bottom = min(total, line + 1 + context_lines)
|
|
||||||
traceback = hasattr(exception, 'traceback') and exception.traceback or ''
|
|
||||||
result = render_to_string('template_debug',
|
|
||||||
DjangoContext(request, {
|
|
||||||
'message' : exception.args[0],
|
|
||||||
'traceback' : traceback,
|
|
||||||
'source_lines' : source_lines[top:bottom],
|
|
||||||
'before' : before,
|
|
||||||
'during': during,
|
|
||||||
'after': after,
|
|
||||||
'top': top ,
|
|
||||||
'bottom': bottom ,
|
|
||||||
'total' : total,
|
|
||||||
'line' : line,
|
|
||||||
'name' : origin.name,
|
|
||||||
}),
|
|
||||||
)
|
|
||||||
return HttpResponseServerError(result)
|
|
@ -6,14 +6,65 @@ from django.conf import settings
|
|||||||
from os.path import dirname, join as pathjoin
|
from os.path import dirname, join as pathjoin
|
||||||
from django.core.template import Template, Context
|
from django.core.template import Template, Context
|
||||||
from django.utils.httpwrappers import HttpResponseServerError, HttpResponseNotFound
|
from django.utils.httpwrappers import HttpResponseServerError, HttpResponseNotFound
|
||||||
|
from itertools import count, izip
|
||||||
|
from django.utils.html import escape
|
||||||
|
|
||||||
HIDDEN_SETTINGS = re.compile('SECRET|PASSWORD')
|
HIDDEN_SETTINGS = re.compile('SECRET|PASSWORD')
|
||||||
|
|
||||||
|
def linebreak_iter(template_source):
|
||||||
|
import re
|
||||||
|
newline_re = re.compile("^", re.M)
|
||||||
|
for match in newline_re.finditer(template_source):
|
||||||
|
yield match.start()
|
||||||
|
yield len(template_source) + 1
|
||||||
|
|
||||||
|
def get_template_exception_info(exc_type,exc_value,tb):
|
||||||
|
origin, (start, end) = exc_value.source
|
||||||
|
template_source = origin.reload()
|
||||||
|
context_lines = 10
|
||||||
|
line = 0
|
||||||
|
upto = 0
|
||||||
|
source_lines = []
|
||||||
|
linebreaks = izip(count(0), linebreak_iter(template_source))
|
||||||
|
linebreaks.next() # skip the nothing before initial line start
|
||||||
|
for num, next in linebreaks:
|
||||||
|
if start >= upto and end <= next :
|
||||||
|
line = num
|
||||||
|
before = escape(template_source[upto:start])
|
||||||
|
during = escape(template_source[start:end])
|
||||||
|
after = escape(template_source[end:next - 1])
|
||||||
|
|
||||||
|
source_lines.append( (num, escape(template_source[upto:next - 1])) )
|
||||||
|
upto = next
|
||||||
|
|
||||||
|
total = len(source_lines)
|
||||||
|
|
||||||
|
top = max(0, line - context_lines)
|
||||||
|
bottom = min(total, line + 1 + context_lines)
|
||||||
|
|
||||||
|
template_info = {
|
||||||
|
'message' : exc_value.args[0],
|
||||||
|
'source_lines' : source_lines[top:bottom],
|
||||||
|
'before' : before,
|
||||||
|
'during': during,
|
||||||
|
'after': after,
|
||||||
|
'top': top ,
|
||||||
|
'bottom': bottom ,
|
||||||
|
'total' : total,
|
||||||
|
'line' : line,
|
||||||
|
'name' : origin.name,
|
||||||
|
}
|
||||||
|
exc_info = hasattr(exc_value, 'exc_info') and exc_value.exc_info or (exc_type,exc_value,tb)
|
||||||
|
return exc_info + (template_info,)
|
||||||
|
|
||||||
def technical_500_response(request, exc_type, exc_value, tb):
|
def technical_500_response(request, exc_type, exc_value, tb):
|
||||||
"""
|
"""
|
||||||
Create a technical server error response. The last three arguments are
|
Create a technical server error response. The last three arguments are
|
||||||
the values returned from sys.exc_info() and friends.
|
the values returned from sys.exc_info() and friends.
|
||||||
"""
|
"""
|
||||||
|
template_info = None
|
||||||
|
if settings.TEMPLATE_DEBUG and hasattr(exc_value, 'source'):
|
||||||
|
exc_type, exc_value, tb, template_info = get_template_exception_info(exc_type,exc_value,tb)
|
||||||
frames = []
|
frames = []
|
||||||
while tb is not None:
|
while tb is not None:
|
||||||
filename = tb.tb_frame.f_code.co_filename
|
filename = tb.tb_frame.f_code.co_filename
|
||||||
@ -53,7 +104,7 @@ def technical_500_response(request, exc_type, exc_value, tb):
|
|||||||
'request' : request,
|
'request' : request,
|
||||||
'request_protocol' : os.environ.get("HTTPS") == "on" and "https" or "http",
|
'request_protocol' : os.environ.get("HTTPS") == "on" and "https" or "http",
|
||||||
'settings' : settings_dict,
|
'settings' : settings_dict,
|
||||||
|
'template_info': template_info,
|
||||||
})
|
})
|
||||||
return HttpResponseServerError(t.render(c))
|
return HttpResponseServerError(t.render(c))
|
||||||
|
|
||||||
@ -144,6 +195,9 @@ TECHNICAL_500_TEMPLATE = """
|
|||||||
#summary table { border:none; background:transparent; }
|
#summary table { border:none; background:transparent; }
|
||||||
#requestinfo h2, #requestinfo h3 { position:relative; margin-left:-100px; }
|
#requestinfo h2, #requestinfo h3 { position:relative; margin-left:-100px; }
|
||||||
#requestinfo h3 { margin-bottom:-1em; }
|
#requestinfo h3 { margin-bottom:-1em; }
|
||||||
|
table.source td{ font-family: monospace; white-space: pre;}
|
||||||
|
span.specific{background:#ffcab7;}
|
||||||
|
.error { background:#ffc; }
|
||||||
</style>
|
</style>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
//<!--
|
//<!--
|
||||||
@ -221,7 +275,24 @@ TECHNICAL_500_TEMPLATE = """
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
|
{%if template_info %}
|
||||||
|
<div id="template">
|
||||||
|
<h2>Template</h2>
|
||||||
|
In template {{template_info.name}}, error at line {{template_info.line}}
|
||||||
|
<div>{{template_info.message|escape}}</div>
|
||||||
|
<table class="source{%if template_info.top%} cut-top{%endif%}{%ifnotequal template_info.bottom template_info.total%} cut-bottom{%endifnotequal%}">
|
||||||
|
{% for source_line in template_info.source_lines %}
|
||||||
|
{%ifequal source_line.0 template_info.line %}
|
||||||
|
<tr class="error"><td>{{source_line.0}}</td>
|
||||||
|
<td> {{template_info.before}}<span class="specific">{{template_info.during}}</span>{{template_info.after}}</td></tr>
|
||||||
|
{%else%}
|
||||||
|
<tr><td>{{source_line.0}}</td>
|
||||||
|
<td> {{source_line.1}}</td></tr>
|
||||||
|
{%endifequal%}
|
||||||
|
{%endfor%}
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{%endif%}
|
||||||
<div id="traceback">
|
<div id="traceback">
|
||||||
<h2>Traceback <span>(innermost last)</span></h2>
|
<h2>Traceback <span>(innermost last)</span></h2>
|
||||||
<ul class="traceback">
|
<ul class="traceback">
|
||||||
|
Loading…
x
Reference in New Issue
Block a user