| 1 |
import os |
|---|
| 2 |
import re |
|---|
| 3 |
import sys |
|---|
| 4 |
import datetime |
|---|
| 5 |
|
|---|
| 6 |
from django.conf import settings |
|---|
| 7 |
from django.template import Template, Context, TemplateDoesNotExist |
|---|
| 8 |
from django.utils.html import escape |
|---|
| 9 |
from django.http import HttpResponse, HttpResponseServerError, HttpResponseNotFound |
|---|
| 10 |
from django.utils.encoding import smart_unicode |
|---|
| 11 |
|
|---|
| 12 |
HIDDEN_SETTINGS = re.compile('SECRET|PASSWORD|PROFANITIES_LIST') |
|---|
| 13 |
|
|---|
| 14 |
def linebreak_iter(template_source): |
|---|
| 15 |
yield 0 |
|---|
| 16 |
p = template_source.find('\n') |
|---|
| 17 |
while p >= 0: |
|---|
| 18 |
yield p+1 |
|---|
| 19 |
p = template_source.find('\n', p+1) |
|---|
| 20 |
yield len(template_source) + 1 |
|---|
| 21 |
|
|---|
| 22 |
def get_safe_settings(): |
|---|
| 23 |
"Returns a dictionary of the settings module, with sensitive settings blurred out." |
|---|
| 24 |
settings_dict = {} |
|---|
| 25 |
for k in dir(settings): |
|---|
| 26 |
if k.isupper(): |
|---|
| 27 |
if HIDDEN_SETTINGS.search(k): |
|---|
| 28 |
settings_dict[k] = '********************' |
|---|
| 29 |
else: |
|---|
| 30 |
settings_dict[k] = getattr(settings, k) |
|---|
| 31 |
return settings_dict |
|---|
| 32 |
|
|---|
| 33 |
def technical_500_response(request, exc_type, exc_value, tb): |
|---|
| 34 |
""" |
|---|
| 35 |
Create a technical server error response. The last three arguments are |
|---|
| 36 |
the values returned from sys.exc_info() and friends. |
|---|
| 37 |
""" |
|---|
| 38 |
reporter = ExceptionReporter(request, exc_type, exc_value, tb) |
|---|
| 39 |
html = reporter.get_traceback_html() |
|---|
| 40 |
return HttpResponseServerError(html, mimetype='text/html') |
|---|
| 41 |
|
|---|
| 42 |
class ExceptionReporter: |
|---|
| 43 |
""" |
|---|
| 44 |
A class to organize and coordinate reporting on exceptions. |
|---|
| 45 |
""" |
|---|
| 46 |
def __init__(self, request, exc_type, exc_value, tb): |
|---|
| 47 |
self.request = request |
|---|
| 48 |
self.exc_type = exc_type |
|---|
| 49 |
self.exc_value = exc_value |
|---|
| 50 |
self.tb = tb |
|---|
| 51 |
|
|---|
| 52 |
self.template_info = None |
|---|
| 53 |
self.template_does_not_exist = False |
|---|
| 54 |
self.loader_debug_info = None |
|---|
| 55 |
|
|---|
| 56 |
# Handle deprecated string exceptions |
|---|
| 57 |
if isinstance(self.exc_type, basestring): |
|---|
| 58 |
self.exc_value = Exception('Deprecated String Exception: %r' % self.exc_type) |
|---|
| 59 |
self.exc_type = type(self.exc_value) |
|---|
| 60 |
|
|---|
| 61 |
def get_traceback_html(self): |
|---|
| 62 |
"Return HTML code for traceback." |
|---|
| 63 |
|
|---|
| 64 |
if issubclass(self.exc_type, TemplateDoesNotExist): |
|---|
| 65 |
from django.template.loader import template_source_loaders |
|---|
| 66 |
self.template_does_not_exist = True |
|---|
| 67 |
self.loader_debug_info = [] |
|---|
| 68 |
for loader in template_source_loaders: |
|---|
| 69 |
try: |
|---|
| 70 |
source_list_func = getattr(__import__(loader.__module__, {}, {}, ['get_template_sources']), 'get_template_sources') |
|---|
| 71 |
# NOTE: This assumes exc_value is the name of the template that |
|---|
| 72 |
# the loader attempted to load. |
|---|
| 73 |
template_list = [{'name': t, 'exists': os.path.exists(t)} \ |
|---|
| 74 |
for t in source_list_func(str(self.exc_value))] |
|---|
| 75 |
except (ImportError, AttributeError): |
|---|
| 76 |
template_list = [] |
|---|
| 77 |
self.loader_debug_info.append({ |
|---|
| 78 |
'loader': loader.__module__ + '.' + loader.__name__, |
|---|
| 79 |
'templates': template_list, |
|---|
| 80 |
}) |
|---|
| 81 |
if settings.TEMPLATE_DEBUG and hasattr(self.exc_value, 'source'): |
|---|
| 82 |
self.get_template_exception_info() |
|---|
| 83 |
|
|---|
| 84 |
frames = self.get_traceback_frames() |
|---|
| 85 |
|
|---|
| 86 |
unicode_hint = '' |
|---|
| 87 |
if issubclass(self.exc_type, UnicodeError): |
|---|
| 88 |
start = getattr(self.exc_value, 'start', None) |
|---|
| 89 |
end = getattr(self.exc_value, 'end', None) |
|---|
| 90 |
if start is not None and end is not None: |
|---|
| 91 |
unicode_str = self.exc_value.args[1] |
|---|
| 92 |
unicode_hint = smart_unicode(unicode_str[max(start-5, 0):min(end+5, len(unicode_str))], 'ascii', errors='replace') |
|---|
| 93 |
from django import get_version |
|---|
| 94 |
t = Template(TECHNICAL_500_TEMPLATE, name='Technical 500 template') |
|---|
| 95 |
c = Context({ |
|---|
| 96 |
'exception_type': self.exc_type.__name__, |
|---|
| 97 |
'exception_value': smart_unicode(self.exc_value, errors='replace'), |
|---|
| 98 |
'unicode_hint': unicode_hint, |
|---|
| 99 |
'frames': frames, |
|---|
| 100 |
'lastframe': frames[-1], |
|---|
| 101 |
'request': self.request, |
|---|
| 102 |
'request_protocol': self.request.is_secure() and "https" or "http", |
|---|
| 103 |
'settings': get_safe_settings(), |
|---|
| 104 |
'sys_executable': sys.executable, |
|---|
| 105 |
'sys_version_info': '%d.%d.%d' % sys.version_info[0:3], |
|---|
| 106 |
'server_time': datetime.datetime.now(), |
|---|
| 107 |
'django_version_info': get_version(), |
|---|
| 108 |
'sys_path' : sys.path, |
|---|
| 109 |
'template_info': self.template_info, |
|---|
| 110 |
'template_does_not_exist': self.template_does_not_exist, |
|---|
| 111 |
'loader_debug_info': self.loader_debug_info, |
|---|
| 112 |
}) |
|---|
| 113 |
return t.render(c) |
|---|
| 114 |
|
|---|
| 115 |
def get_template_exception_info(self): |
|---|
| 116 |
origin, (start, end) = self.exc_value.source |
|---|
| 117 |
template_source = origin.reload() |
|---|
| 118 |
context_lines = 10 |
|---|
| 119 |
line = 0 |
|---|
| 120 |
upto = 0 |
|---|
| 121 |
source_lines = [] |
|---|
| 122 |
before = during = after = "" |
|---|
| 123 |
for num, next in enumerate(linebreak_iter(template_source)): |
|---|
| 124 |
if start >= upto and end <= next: |
|---|
| 125 |
line = num |
|---|
| 126 |
before = escape(template_source[upto:start]) |
|---|
| 127 |
during = escape(template_source[start:end]) |
|---|
| 128 |
after = escape(template_source[end:next]) |
|---|
| 129 |
source_lines.append( (num, escape(template_source[upto:next])) ) |
|---|
| 130 |
upto = next |
|---|
| 131 |
total = len(source_lines) |
|---|
| 132 |
|
|---|
| 133 |
top = max(1, line - context_lines) |
|---|
| 134 |
bottom = min(total, line + 1 + context_lines) |
|---|
| 135 |
|
|---|
| 136 |
self.template_info = { |
|---|
| 137 |
'message': self.exc_value.args[0], |
|---|
| 138 |
'source_lines': source_lines[top:bottom], |
|---|
| 139 |
'before': before, |
|---|
| 140 |
'during': during, |
|---|
| 141 |
'after': after, |
|---|
| 142 |
'top': top, |
|---|
| 143 |
'bottom': bottom, |
|---|
| 144 |
'total': total, |
|---|
| 145 |
'line': line, |
|---|
| 146 |
'name': origin.name, |
|---|
| 147 |
} |
|---|
| 148 |
|
|---|
| 149 |
def _get_lines_from_file(self, filename, lineno, context_lines, loader=None, module_name=None): |
|---|
| 150 |
""" |
|---|
| 151 |
Returns context_lines before and after lineno from file. |
|---|
| 152 |
Returns (pre_context_lineno, pre_context, context_line, post_context). |
|---|
| 153 |
""" |
|---|
| 154 |
source = None |
|---|
| 155 |
if loader is not None and hasattr(loader, "get_source"): |
|---|
| 156 |
source = loader.get_source(module_name) |
|---|
| 157 |
if source is not None: |
|---|
| 158 |
source = source.splitlines() |
|---|
| 159 |
if source is None: |
|---|
| 160 |
try: |
|---|
| 161 |
f = open(filename) |
|---|
| 162 |
try: |
|---|
| 163 |
source = f.readlines() |
|---|
| 164 |
finally: |
|---|
| 165 |
f.close() |
|---|
| 166 |
except (OSError, IOError): |
|---|
| 167 |
pass |
|---|
| 168 |
if source is None: |
|---|
| 169 |
return None, [], None, [] |
|---|
| 170 |
|
|---|
| 171 |
encoding = 'ascii' |
|---|
| 172 |
for line in source[:2]: |
|---|
| 173 |
# File coding may be specified. Match pattern from PEP-263 |
|---|
| 174 |
# (http://www.python.org/dev/peps/pep-0263/) |
|---|
| 175 |
match = re.search(r'coding[:=]\s*([-\w.]+)', line) |
|---|
| 176 |
if match: |
|---|
| 177 |
encoding = match.group(1) |
|---|
| 178 |
break |
|---|
| 179 |
source = [unicode(sline, encoding, 'replace') for sline in source] |
|---|
| 180 |
|
|---|
| 181 |
lower_bound = max(0, lineno - context_lines) |
|---|
| 182 |
upper_bound = lineno + context_lines |
|---|
| 183 |
|
|---|
| 184 |
pre_context = [line.strip('\n') for line in source[lower_bound:lineno]] |
|---|
| 185 |
context_line = source[lineno].strip('\n') |
|---|
| 186 |
post_context = [line.strip('\n') for line in source[lineno+1:upper_bound]] |
|---|
| 187 |
|
|---|
| 188 |
return lower_bound, pre_context, context_line, post_context |
|---|
| 189 |
|
|---|
| 190 |
def get_traceback_frames(self): |
|---|
| 191 |
frames = [] |
|---|
| 192 |
tb = self.tb |
|---|
| 193 |
while tb is not None: |
|---|
| 194 |
# support for __traceback_hide__ which is used by a few libraries |
|---|
| 195 |
# to hide internal frames. |
|---|
| 196 |
if tb.tb_frame.f_locals.get('__traceback_hide__'): |
|---|
| 197 |
tb = tb.tb_next |
|---|
| 198 |
continue |
|---|
| 199 |
filename = tb.tb_frame.f_code.co_filename |
|---|
| 200 |
function = tb.tb_frame.f_code.co_name |
|---|
| 201 |
lineno = tb.tb_lineno - 1 |
|---|
| 202 |
loader = tb.tb_frame.f_globals.get('__loader__') |
|---|
| 203 |
module_name = tb.tb_frame.f_globals.get('__name__') |
|---|
| 204 |
pre_context_lineno, pre_context, context_line, post_context = self._get_lines_from_file(filename, lineno, 7, loader, module_name) |
|---|
| 205 |
if pre_context_lineno is not None: |
|---|
| 206 |
frames.append({ |
|---|
| 207 |
'tb': tb, |
|---|
| 208 |
'filename': filename, |
|---|
| 209 |
'function': function, |
|---|
| 210 |
'lineno': lineno + 1, |
|---|
| 211 |
'vars': tb.tb_frame.f_locals.items(), |
|---|
| 212 |
'id': id(tb), |
|---|
| 213 |
'pre_context': pre_context, |
|---|
| 214 |
'context_line': context_line, |
|---|
| 215 |
'post_context': post_context, |
|---|
| 216 |
'pre_context_lineno': pre_context_lineno + 1, |
|---|
| 217 |
}) |
|---|
| 218 |
tb = tb.tb_next |
|---|
| 219 |
|
|---|
| 220 |
if not frames: |
|---|
| 221 |
frames = [{ |
|---|
| 222 |
'filename': '<unknown>', |
|---|
| 223 |
'function': '?', |
|---|
| 224 |
'lineno': '?', |
|---|
| 225 |
'context_line': '???', |
|---|
| 226 |
}] |
|---|
| 227 |
|
|---|
| 228 |
return frames |
|---|
| 229 |
|
|---|
| 230 |
def format_exception(self): |
|---|
| 231 |
""" |
|---|
| 232 |
Return the same data as from traceback.format_exception. |
|---|
| 233 |
""" |
|---|
| 234 |
import traceback |
|---|
| 235 |
frames = self.get_traceback_frames() |
|---|
| 236 |
tb = [ (f['filename'], f['lineno'], f['function'], f['context_line']) for f in frames ] |
|---|
| 237 |
list = ['Traceback (most recent call last):\n'] |
|---|
| 238 |
list += traceback.format_list(tb) |
|---|
| 239 |
list += traceback.format_exception_only(self.exc_type, self.exc_value) |
|---|
| 240 |
return list |
|---|
| 241 |
|
|---|
| 242 |
|
|---|
| 243 |
def technical_404_response(request, exception): |
|---|
| 244 |
"Create a technical 404 error response. The exception should be the Http404." |
|---|
| 245 |
try: |
|---|
| 246 |
tried = exception.args[0]['tried'] |
|---|
| 247 |
except (IndexError, TypeError): |
|---|
| 248 |
tried = [] |
|---|
| 249 |
else: |
|---|
| 250 |
if not tried: |
|---|
| 251 |
# tried exists but is an empty list. The URLconf must've been empty. |
|---|
| 252 |
return empty_urlconf(request) |
|---|
| 253 |
|
|---|
| 254 |
t = Template(TECHNICAL_404_TEMPLATE, name='Technical 404 template') |
|---|
| 255 |
c = Context({ |
|---|
| 256 |
'root_urlconf': settings.ROOT_URLCONF, |
|---|
| 257 |
'request_path': request.path[1:], # Trim leading slash |
|---|
| 258 |
'urlpatterns': tried, |
|---|
| 259 |
'reason': str(exception), |
|---|
| 260 |
'request': request, |
|---|
| 261 |
'request_protocol': request.is_secure() and "https" or "http", |
|---|
| 262 |
'settings': get_safe_settings(), |
|---|
| 263 |
}) |
|---|
| 264 |
return HttpResponseNotFound(t.render(c), mimetype='text/html') |
|---|
| 265 |
|
|---|
| 266 |
def empty_urlconf(request): |
|---|
| 267 |
"Create an empty URLconf 404 error response." |
|---|
| 268 |
t = Template(EMPTY_URLCONF_TEMPLATE, name='Empty URLConf template') |
|---|
| 269 |
c = Context({ |
|---|
| 270 |
'project_name': settings.SETTINGS_MODULE.split('.')[0] |
|---|
| 271 |
}) |
|---|
| 272 |
return HttpResponse(t.render(c), mimetype='text/html') |
|---|
| 273 |
|
|---|
| 274 |
# |
|---|
| 275 |
# Templates are embedded in the file so that we know the error handler will |
|---|
| 276 |
# always work even if the template loader is broken. |
|---|
| 277 |
# |
|---|
| 278 |
|
|---|
| 279 |
TECHNICAL_500_TEMPLATE = """ |
|---|
| 280 |
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
|---|
| 281 |
<html lang="en"> |
|---|
| 282 |
<head> |
|---|
| 283 |
<meta http-equiv="content-type" content="text/html; charset=utf-8"> |
|---|
| 284 |
<meta name="robots" content="NONE,NOARCHIVE"> |
|---|
| 285 |
<title>{{ exception_type }} at {{ request.path|escape }}</title> |
|---|
| 286 |
<style type="text/css"> |
|---|
| 287 |
html * { padding:0; margin:0; } |
|---|
| 288 |
body * { padding:10px 20px; } |
|---|
| 289 |
body * * { padding:0; } |
|---|
| 290 |
body { font:small sans-serif; } |
|---|
| 291 |
body>div { border-bottom:1px solid #ddd; } |
|---|
| 292 |
h1 { font-weight:normal; } |
|---|
| 293 |
h2 { margin-bottom:.8em; } |
|---|
| 294 |
h2 span { font-size:80%; color:#666; font-weight:normal; } |
|---|
| 295 |
h3 { margin:1em 0 .5em 0; } |
|---|
| 296 |
h4 { margin:0 0 .5em 0; font-weight: normal; } |
|---|
| 297 |
table { border:1px solid #ccc; border-collapse: collapse; width:100%; background:white; } |
|---|
| 298 |
tbody td, tbody th { vertical-align:top; padding:2px 3px; } |
|---|
| 299 |
thead th { padding:1px 6px 1px 3px; background:#fefefe; text-align:left; font-weight:normal; font-size:11px; border:1px solid #ddd; } |
|---|
| 300 |
tbody th { width:12em; text-align:right; color:#666; padding-right:.5em; } |
|---|
| 301 |
table.vars { margin:5px 0 2px 40px; } |
|---|
| 302 |
table.vars td, table.req td { font-family:monospace; } |
|---|
| 303 |
table td.code { width:100%; } |
|---|
| 304 |
table td.code div { overflow:hidden; } |
|---|
| 305 |
table.source th { color:#666; } |
|---|
| 306 |
table.source td { font-family:monospace; white-space:pre; border-bottom:1px solid #eee; } |
|---|
| 307 |
ul.traceback { list-style-type:none; } |
|---|
| 308 |
ul.traceback li.frame { margin-bottom:1em; } |
|---|
| 309 |
div.context { margin: 10px 0; } |
|---|
| 310 |
div.context ol { padding-left:30px; margin:0 10px; list-style-position: inside; } |
|---|
| 311 |
div.context ol li { font-family:monospace; white-space:pre; color:#666; cursor:pointer; } |
|---|
| 312 |
div.context ol.context-line li { color:black; background-color:#ccc; } |
|---|
| 313 |
div.context ol.context-line li span { float: right; } |
|---|
| 314 |
div.commands { margin-left: 40px; } |
|---|
| 315 |
div.commands a { color:black; text-decoration:none; } |
|---|
| 316 |
#summary { background: #ffc; } |
|---|
| 317 |
#summary h2 { font-weight: normal; color: #666; } |
|---|
| 318 |
#explanation { background:#eee; } |
|---|
| 319 |
#template, #template-not-exist { background:#f6f6f6; } |
|---|
| 320 |
#template-not-exist ul { margin: 0 0 0 20px; } |
|---|
| 321 |
#unicode-hint { background:#eee; } |
|---|
| 322 |
#traceback { background:#eee; } |
|---|
| 323 |
#requestinfo { background:#f6f6f6; padding-left:120px; } |
|---|
| 324 |
#summary table { border:none; background:transparent; } |
|---|
| 325 |
#requestinfo h2, #requestinfo h3 { position:relative; margin-left:-100px; } |
|---|
| 326 |
#requestinfo h3 { margin-bottom:-1em; } |
|---|
| 327 |
.error { background: #ffc; } |
|---|
| 328 |
.specific { color:#cc3300; font-weight:bold; } |
|---|
| 329 |
h2 span.commands { font-size:.7em;} |
|---|
| 330 |
span.commands a:link {color:#5E5694;} |
|---|
| 331 |
</style> |
|---|
| 332 |
<script type="text/javascript"> |
|---|
| 333 |
//<!-- |
|---|
| 334 |
function getElementsByClassName(oElm, strTagName, strClassName){ |
|---|
| 335 |
// Written by Jonathan Snook, http://www.snook.ca/jon; Add-ons by Robert Nyman, http://www.robertnyman.com |
|---|
| 336 |
var arrElements = (strTagName == "*" && document.all)? document.all : |
|---|
| 337 |
oElm.getElementsByTagName(strTagName); |
|---|
| 338 |
var arrReturnElements = new Array(); |
|---|
| 339 |
strClassName = strClassName.replace(/\-/g, "\\-"); |
|---|
| 340 |
var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)"); |
|---|
| 341 |
var oElement; |
|---|
| 342 |
for(var i=0; i<arrElements.length; i++){ |
|---|
| 343 |
oElement = arrElements[i]; |
|---|
| 344 |
if(oRegExp.test(oElement.className)){ |
|---|
| 345 |
arrReturnElements.push(oElement); |
|---|
| 346 |
} |
|---|
| 347 |
} |
|---|
| 348 |
return (arrReturnElements) |
|---|
| 349 |
} |
|---|
| 350 |
function hideAll(elems) { |
|---|
| 351 |
for (var e = 0; e < elems.length; e++) { |
|---|
| 352 |
elems[e].style.display = 'none'; |
|---|
| 353 |
} |
|---|
| 354 |
} |
|---|
| 355 |
window.onload = function() { |
|---|
| 356 |
hideAll(getElementsByClassName(document, 'table', 'vars')); |
|---|
| 357 |
hideAll(getElementsByClassName(document, 'ol', 'pre-context')); |
|---|
| 358 |
hideAll(getElementsByClassName(document, 'ol', 'post-context')); |
|---|
| 359 |
hideAll(getElementsByClassName(document, 'div', 'pastebin')); |
|---|
| 360 |
} |
|---|
| 361 |
function toggle() { |
|---|
| 362 |
for (var i = 0; i < arguments.length; i++) { |
|---|
| 363 |
var e = document.getElementById(arguments[i]); |
|---|
| 364 |
if (e) { |
|---|
| 365 |
e.style.display = e.style.display == 'none' ? 'block' : 'none'; |
|---|
| 366 |
} |
|---|
| 367 |
} |
|---|
| 368 |
return false; |
|---|
| 369 |
} |
|---|
| 370 |
function varToggle(link, id) { |
|---|
| 371 |
toggle('v' + id); |
|---|
| 372 |
var s = link.getElementsByTagName('span')[0]; |
|---|
| 373 |
var uarr = String.fromCharCode(0x25b6); |
|---|
| 374 |
var darr = String.fromCharCode(0x25bc); |
|---|
| 375 |
s.innerHTML = s.innerHTML == uarr ? darr : uarr; |
|---|
| 376 |
return false; |
|---|
| 377 |
} |
|---|
| 378 |
function switchPastebinFriendly(link) { |
|---|
| 379 |
s1 = "Switch to copy-and-paste view"; |
|---|
| 380 |
s2 = "Switch back to interactive view"; |
|---|
| 381 |
link.innerHTML = link.innerHTML == s1 ? s2 : s1; |
|---|
| 382 |
toggle('browserTraceback', 'pastebinTraceback'); |
|---|
| 383 |
return false; |
|---|
| 384 |
} |
|---|
| 385 |
//--> |
|---|
| 386 |
</script> |
|---|
| 387 |
</head> |
|---|
| 388 |
<body> |
|---|
| 389 |
<div id="summary"> |
|---|
| 390 |
<h1>{{ exception_type }} at {{ request.path|escape }}</h1> |
|---|
| 391 |
<h2>{{ exception_value|escape }}</h2> |
|---|
| 392 |
<table class="meta"> |
|---|
| 393 |
<tr> |
|---|
| 394 |
<th>Request Method:</th> |
|---|
| 395 |
<td>{{ request.META.REQUEST_METHOD }}</td> |
|---|
| 396 |
</tr> |
|---|
| 397 |
<tr> |
|---|
| 398 |
<th>Request URL:</th> |
|---|
| 399 |
<td>{{ request_protocol }}://{{ request.META.HTTP_HOST }}{{ request.path|escape }}</td> |
|---|
| 400 |
</tr> |
|---|
| 401 |
<tr> |
|---|
| 402 |
<th>Exception Type:</th> |
|---|
| 403 |
<td>{{ exception_type }}</td> |
|---|
| 404 |
</tr> |
|---|
| 405 |
<tr> |
|---|
| 406 |
<th>Exception Value:</th> |
|---|
| 407 |
<td>{{ exception_value|escape }}</td> |
|---|
| 408 |
</tr> |
|---|
| 409 |
<tr> |
|---|
| 410 |
<th>Exception Location:</th> |
|---|
| 411 |
<td>{{ lastframe.filename|escape }} in {{ lastframe.function|escape }}, line {{ lastframe.lineno }}</td> |
|---|
| 412 |
</tr> |
|---|
| 413 |
<tr> |
|---|
| 414 |
<th>Python Executable:</th> |
|---|
| 415 |
<td>{{ sys_executable|escape }}</td> |
|---|
| 416 |
</tr> |
|---|
| 417 |
<tr> |
|---|
| 418 |
<th>Python Version:</th> |
|---|
| 419 |
<td>{{ sys_version_info }}</td> |
|---|
| 420 |
</tr> |
|---|
| 421 |
<tr> |
|---|
| 422 |
<th>Python Path:</th> |
|---|
| 423 |
<td>{{ sys_path }}</td> |
|---|
| 424 |
</tr> |
|---|
| 425 |
<tr> |
|---|
| 426 |
<th>Server time:</th> |
|---|
| 427 |
<td>{{server_time|date:"r"}}</td> |
|---|
| 428 |
</tr> |
|---|
| 429 |
</table> |
|---|
| 430 |
</div> |
|---|
| 431 |
{% if unicode_hint %} |
|---|
| 432 |
<div id="unicode-hint"> |
|---|
| 433 |
<h2>Unicode error hint</h2> |
|---|
| 434 |
<p>The string that could not be encoded/decoded was: <strong>{{ unicode_hint|escape }}</strong></p> |
|---|
| 435 |
</div> |
|---|
| 436 |
{% endif %} |
|---|
| 437 |
{% if template_does_not_exist %} |
|---|
| 438 |
<div id="template-not-exist"> |
|---|
| 439 |
<h2>Template-loader postmortem</h2> |
|---|
| 440 |
{% if loader_debug_info %} |
|---|
| 441 |
<p>Django tried loading these templates, in this order:</p> |
|---|
| 442 |
<ul> |
|---|
| 443 |
{% for loader in loader_debug_info %} |
|---|
| 444 |
<li>Using loader <code>{{ loader.loader }}</code>: |
|---|
| 445 |
<ul>{% for t in loader.templates %}<li><code>{{ t.name }}</code> (File {% if t.exists %}exists{% else %}does not exist{% endif %})</li>{% endfor %}</ul> |
|---|
| 446 |
</li> |
|---|
| 447 |
{% endfor %} |
|---|
| 448 |
</ul> |
|---|
| 449 |
{% else %} |
|---|
| 450 |
<p>Django couldn't find any templates because your <code>TEMPLATE_LOADERS</code> setting is empty!</p> |
|---|
| 451 |
{% endif %} |
|---|
| 452 |
</div> |
|---|
| 453 |
{% endif %} |
|---|
| 454 |
{% if template_info %} |
|---|
| 455 |
<div id="template"> |
|---|
| 456 |
<h2>Template error</h2> |
|---|
| 457 |
<p>In template <code>{{ template_info.name }}</code>, error at line <strong>{{ template_info.line }}</strong></p> |
|---|
| 458 |
<h3>{{ template_info.message }}</h3> |
|---|
| 459 |
<table class="source{% if template_info.top %} cut-top{% endif %}{% ifnotequal template_info.bottom template_info.total %} cut-bottom{% endifnotequal %}"> |
|---|
| 460 |
{% for source_line in template_info.source_lines %} |
|---|
| 461 |
{% ifequal source_line.0 template_info.line %} |
|---|
| 462 |
<tr class="error"><th>{{ source_line.0 }}</th> |
|---|
| 463 |
<td>{{ template_info.before }}<span class="specific">{{ template_info.during }}</span>{{ template_info.after }}</td></tr> |
|---|
| 464 |
{% else %} |
|---|
| 465 |
<tr><th>{{ source_line.0 }}</th> |
|---|
| 466 |
<td>{{ source_line.1 }}</td></tr> |
|---|
| 467 |
{% endifequal %} |
|---|
| 468 |
{% endfor %} |
|---|
| 469 |
</table> |
|---|
| 470 |
</div> |
|---|
| 471 |
{% endif %} |
|---|
| 472 |
<div id="traceback"> |
|---|
| 473 |
<h2>Traceback <span class="commands"><a href="#" onclick="return switchPastebinFriendly(this);">Switch to copy-and-paste view</a></span></h2> |
|---|
| 474 |
{% autoescape off %} |
|---|
| 475 |
<div id="browserTraceback"> |
|---|
| 476 |
<ul class="traceback"> |
|---|
| 477 |
{% for frame in frames %} |
|---|
| 478 |
<li class="frame"> |
|---|
| 479 |
<code>{{ frame.filename|escape }}</code> in <code>{{ frame.function|escape }}</code> |
|---|
| 480 |
|
|---|
| 481 |
{% if frame.context_line %} |
|---|
| 482 |
<div class="context" id="c{{ frame.id }}"> |
|---|
| 483 |
{% if frame.pre_context %} |
|---|
| 484 |
<ol start="{{ frame.pre_context_lineno }}" class="pre-context" id="pre{{ frame.id }}">{% for line in frame.pre_context %}<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')">{{ line|escape }}</li>{% endfor %}</ol> |
|---|
| 485 |
{% endif %} |
|---|
| 486 |
<ol start="{{ frame.lineno }}" class="context-line"><li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')">{{ frame.context_line|escape }} <span>...</span></li></ol> |
|---|
| 487 |
{% if frame.post_context %} |
|---|
| 488 |
<ol start='{{ frame.lineno|add:"1" }}' class="post-context" id="post{{ frame.id }}">{% for line in frame.post_context %}<li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')">{{ line|escape }}</li>{% endfor %}</ol> |
|---|
| 489 |
{% endif %} |
|---|
| 490 |
</div> |
|---|
| 491 |
{% endif %} |
|---|
| 492 |
|
|---|
| 493 |
{% if frame.vars %} |
|---|
| 494 |
<div class="commands"> |
|---|
| 495 |
<a href="#" onclick="return varToggle(this, '{{ frame.id }}')"><span>▶</span> Local vars</a> |
|---|
| 496 |
</div> |
|---|
| 497 |
<table class="vars" id="v{{ frame.id }}"> |
|---|
| 498 |
<thead> |
|---|
| 499 |
<tr> |
|---|
| 500 |
<th>Variable</th> |
|---|
| 501 |
<th>Value</th> |
|---|
| 502 |
</tr> |
|---|
| 503 |
</thead> |
|---|
| 504 |
<tbody> |
|---|
| 505 |
{% for var in frame.vars|dictsort:"0" %} |
|---|
| 506 |
<tr> |
|---|
| 507 |
<td>{{ var.0|escape }}</td> |
|---|
| 508 |
<td class="code"><div>{{ var.1|pprint|escape }}</div></td> |
|---|
| 509 |
</tr> |
|---|
| 510 |
{% endfor %} |
|---|
| 511 |
</tbody> |
|---|
| 512 |
</table> |
|---|
| 513 |
{% endif %} |
|---|
| 514 |
</li> |
|---|
| 515 |
{% endfor %} |
|---|
| 516 |
</ul> |
|---|
| 517 |
</div> |
|---|
| 518 |
{% endautoescape %} |
|---|
| 519 |
<form action="http://dpaste.com/" name="pasteform" id="pasteform" method="post"> |
|---|
| 520 |
<div id="pastebinTraceback" class="pastebin"> |
|---|
| 521 |
<input type="hidden" name="language" value="PythonConsole"> |
|---|
| 522 |
<input type="hidden" name="title" value="{{ exception_type|escape }} at {{ request.path|escape }}"> |
|---|
| 523 |
<input type="hidden" name="source" value="Django Dpaste Agent"> |
|---|
| 524 |
<input type="hidden" name="poster" value="Django"> |
|---|
| 525 |
<textarea name="content" id="traceback_area" cols="140" rows="25"> |
|---|
| 526 |
Environment: |
|---|
| 527 |
|
|---|
| 528 |
Request Method: {{ request.META.REQUEST_METHOD }} |
|---|
| 529 |
Request URL: {{ request_protocol }}://{{ request.META.HTTP_HOST }}{{ request.path|escape }} |
|---|
| 530 |
Django Version: {{ django_version_info }} |
|---|
| 531 |
Python Version: {{ sys_version_info }} |
|---|
| 532 |
Installed Applications: |
|---|
| 533 |
{{ settings.INSTALLED_APPS|pprint }} |
|---|
| 534 |
Installed Middleware: |
|---|
| 535 |
{{ settings.MIDDLEWARE_CLASSES|pprint }} |
|---|
| 536 |
|
|---|
| 537 |
{% if template_does_not_exist %}Template Loader Error: |
|---|
| 538 |
{% if loader_debug_info %}Django tried loading these templates, in this order: |
|---|
| 539 |
{% for loader in loader_debug_info %}Using loader {{ loader.loader }}: |
|---|
| 540 |
{% for t in loader.templates %}{{ t.name }} (File {% if t.exists %}exists{% else %}does not exist{% endif %}) |
|---|
| 541 |
{% endfor %}{% endfor %} |
|---|
| 542 |
{% else %}Django couldn't find any templates because your TEMPLATE_LOADERS setting is empty! |
|---|
| 543 |
{% endif %} |
|---|
| 544 |
{% endif %}{% if template_info %} |
|---|
| 545 |
Template error: |
|---|
| 546 |
In template {{ template_info.name }}, error at line {{ template_info.line }} |
|---|
| 547 |
{{ template_info.message }}{% for source_line in template_info.source_lines %}{% ifequal source_line.0 template_info.line %} |
|---|
| 548 |
{{ source_line.0 }} : {{ template_info.before }} {{ template_info.during }} {{ template_info.after }} |
|---|
| 549 |
{% else %} |
|---|
| 550 |
{{ source_line.0 }} : {{ source_line.1 }} |
|---|
| 551 |
{% endifequal %}{% endfor %}{% endif %} |
|---|
| 552 |
Traceback: |
|---|
| 553 |
{% for frame in frames %}File "{{ frame.filename|escape }}" in {{ frame.function|escape }} |
|---|
| 554 |
{% if frame.context_line %} {{ frame.lineno }}. {{ frame.context_line|escape }}{% endif %} |
|---|
| 555 |
{% endfor %} |
|---|
| 556 |
Exception Type: {{ exception_type|escape }} at {{ request.path|escape }} |
|---|
| 557 |
Exception Value: {{ exception_value|escape }} |
|---|
| 558 |
</textarea> |
|---|
| 559 |
<br><br> |
|---|
| 560 |
<input type="submit" value="Share this traceback on a public Web site"> |
|---|
| 561 |
</div> |
|---|
| 562 |
</form> |
|---|
| 563 |
</div> |
|---|
| 564 |
|
|---|
| 565 |
<div id="requestinfo"> |
|---|
| 566 |
<h2>Request information</h2> |
|---|
| 567 |
|
|---|
| 568 |
<h3 id="get-info">GET</h3> |
|---|
| 569 |
{% if request.GET %} |
|---|
| 570 |
<table class="req"> |
|---|
| 571 |
<thead> |
|---|
| 572 |
<tr> |
|---|
| 573 |
<th>Variable</th> |
|---|
| 574 |
<th>Value</th> |
|---|
| 575 |
</tr> |
|---|
| 576 |
</thead> |
|---|
| 577 |
<tbody> |
|---|
| 578 |
{% for var in request.GET.items %} |
|---|
| 579 |
<tr> |
|---|
| 580 |
<td>{{ var.0 }}</td> |
|---|
| 581 |
<td class="code"><div>{{ var.1|pprint }}</div></td> |
|---|
| 582 |
</tr> |
|---|
| 583 |
{% endfor %} |
|---|
| 584 |
</tbody> |
|---|
| 585 |
</table> |
|---|
| 586 |
{% else %} |
|---|
| 587 |
<p>No GET data</p> |
|---|
| 588 |
{% endif %} |
|---|
| 589 |
|
|---|
| 590 |
<h3 id="post-info">POST</h3> |
|---|
| 591 |
{% if request.POST %} |
|---|
| 592 |
<table class="req"> |
|---|
| 593 |
<thead> |
|---|
| 594 |
<tr> |
|---|
| 595 |
<th>Variable</th> |
|---|
| 596 |
<th>Value</th> |
|---|
| 597 |
</tr> |
|---|
| 598 |
</thead> |
|---|
| 599 |
<tbody> |
|---|
| 600 |
{% for var in request.POST.items %} |
|---|
| 601 |
<tr> |
|---|
| 602 |
&l |
|---|