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