PageRenderTime 69ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/django/views/debug.py

https://github.com/andnils/django
Python | 1168 lines | 1068 code | 43 blank | 57 comment | 77 complexity | 3aea1ca2df07c73ad71b5d3a20840758 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. from __future__ import unicode_literals
  2. import datetime
  3. import os
  4. import re
  5. import sys
  6. import types
  7. from django.conf import settings
  8. from django.http import (HttpResponse, HttpResponseServerError,
  9. HttpResponseNotFound, HttpRequest, build_request_repr)
  10. from django.template import Template, Context, TemplateDoesNotExist
  11. from django.template.defaultfilters import force_escape, pprint
  12. from django.utils.datastructures import MultiValueDict
  13. from django.utils.html import escape
  14. from django.utils.encoding import force_bytes, smart_text
  15. from django.utils.module_loading import import_string
  16. from django.utils import six
  17. HIDDEN_SETTINGS = re.compile('API|TOKEN|KEY|SECRET|PASS|SIGNATURE')
  18. CLEANSED_SUBSTITUTE = '********************'
  19. def linebreak_iter(template_source):
  20. yield 0
  21. p = template_source.find('\n')
  22. while p >= 0:
  23. yield p + 1
  24. p = template_source.find('\n', p + 1)
  25. yield len(template_source) + 1
  26. def cleanse_setting(key, value):
  27. """Cleanse an individual setting key/value of sensitive content.
  28. If the value is a dictionary, recursively cleanse the keys in
  29. that dictionary.
  30. """
  31. try:
  32. if HIDDEN_SETTINGS.search(key):
  33. cleansed = CLEANSED_SUBSTITUTE
  34. else:
  35. if isinstance(value, dict):
  36. cleansed = dict((k, cleanse_setting(k, v)) for k, v in value.items())
  37. else:
  38. cleansed = value
  39. except TypeError:
  40. # If the key isn't regex-able, just return as-is.
  41. cleansed = value
  42. if callable(cleansed):
  43. cleansed.do_not_call_in_templates = True
  44. return cleansed
  45. def get_safe_settings():
  46. "Returns a dictionary of the settings module, with sensitive settings blurred out."
  47. settings_dict = {}
  48. for k in dir(settings):
  49. if k.isupper():
  50. settings_dict[k] = cleanse_setting(k, getattr(settings, k))
  51. return settings_dict
  52. def technical_500_response(request, exc_type, exc_value, tb):
  53. """
  54. Create a technical server error response. The last three arguments are
  55. the values returned from sys.exc_info() and friends.
  56. """
  57. reporter = ExceptionReporter(request, exc_type, exc_value, tb)
  58. if request.is_ajax():
  59. text = reporter.get_traceback_text()
  60. return HttpResponseServerError(text, content_type='text/plain')
  61. else:
  62. html = reporter.get_traceback_html()
  63. return HttpResponseServerError(html, content_type='text/html')
  64. # Cache for the default exception reporter filter instance.
  65. default_exception_reporter_filter = None
  66. def get_exception_reporter_filter(request):
  67. global default_exception_reporter_filter
  68. if default_exception_reporter_filter is None:
  69. # Load the default filter for the first time and cache it.
  70. default_exception_reporter_filter = import_string(
  71. settings.DEFAULT_EXCEPTION_REPORTER_FILTER)()
  72. if request:
  73. return getattr(request, 'exception_reporter_filter', default_exception_reporter_filter)
  74. else:
  75. return default_exception_reporter_filter
  76. class ExceptionReporterFilter(object):
  77. """
  78. Base for all exception reporter filter classes. All overridable hooks
  79. contain lenient default behaviors.
  80. """
  81. def get_request_repr(self, request):
  82. if request is None:
  83. return repr(None)
  84. else:
  85. return build_request_repr(request, POST_override=self.get_post_parameters(request))
  86. def get_post_parameters(self, request):
  87. if request is None:
  88. return {}
  89. else:
  90. return request.POST
  91. def get_traceback_frame_variables(self, request, tb_frame):
  92. return list(six.iteritems(tb_frame.f_locals))
  93. class SafeExceptionReporterFilter(ExceptionReporterFilter):
  94. """
  95. Use annotations made by the sensitive_post_parameters and
  96. sensitive_variables decorators to filter out sensitive information.
  97. """
  98. def is_active(self, request):
  99. """
  100. This filter is to add safety in production environments (i.e. DEBUG
  101. is False). If DEBUG is True then your site is not safe anyway.
  102. This hook is provided as a convenience to easily activate or
  103. deactivate the filter on a per request basis.
  104. """
  105. return settings.DEBUG is False
  106. def get_cleansed_multivaluedict(self, request, multivaluedict):
  107. """
  108. Replaces the keys in a MultiValueDict marked as sensitive with stars.
  109. This mitigates leaking sensitive POST parameters if something like
  110. request.POST['nonexistent_key'] throws an exception (#21098).
  111. """
  112. sensitive_post_parameters = getattr(request, 'sensitive_post_parameters', [])
  113. if self.is_active(request) and sensitive_post_parameters:
  114. multivaluedict = multivaluedict.copy()
  115. for param in sensitive_post_parameters:
  116. if param in multivaluedict:
  117. multivaluedict[param] = CLEANSED_SUBSTITUTE
  118. return multivaluedict
  119. def get_post_parameters(self, request):
  120. """
  121. Replaces the values of POST parameters marked as sensitive with
  122. stars (*********).
  123. """
  124. if request is None:
  125. return {}
  126. else:
  127. sensitive_post_parameters = getattr(request, 'sensitive_post_parameters', [])
  128. if self.is_active(request) and sensitive_post_parameters:
  129. cleansed = request.POST.copy()
  130. if sensitive_post_parameters == '__ALL__':
  131. # Cleanse all parameters.
  132. for k, v in cleansed.items():
  133. cleansed[k] = CLEANSED_SUBSTITUTE
  134. return cleansed
  135. else:
  136. # Cleanse only the specified parameters.
  137. for param in sensitive_post_parameters:
  138. if param in cleansed:
  139. cleansed[param] = CLEANSED_SUBSTITUTE
  140. return cleansed
  141. else:
  142. return request.POST
  143. def cleanse_special_types(self, request, value):
  144. if isinstance(value, HttpRequest):
  145. # Cleanse the request's POST parameters.
  146. value = self.get_request_repr(value)
  147. elif isinstance(value, MultiValueDict):
  148. # Cleanse MultiValueDicts (request.POST is the one we usually care about)
  149. value = self.get_cleansed_multivaluedict(request, value)
  150. return value
  151. def get_traceback_frame_variables(self, request, tb_frame):
  152. """
  153. Replaces the values of variables marked as sensitive with
  154. stars (*********).
  155. """
  156. # Loop through the frame's callers to see if the sensitive_variables
  157. # decorator was used.
  158. current_frame = tb_frame.f_back
  159. sensitive_variables = None
  160. while current_frame is not None:
  161. if (current_frame.f_code.co_name == 'sensitive_variables_wrapper'
  162. and 'sensitive_variables_wrapper' in current_frame.f_locals):
  163. # The sensitive_variables decorator was used, so we take note
  164. # of the sensitive variables' names.
  165. wrapper = current_frame.f_locals['sensitive_variables_wrapper']
  166. sensitive_variables = getattr(wrapper, 'sensitive_variables', None)
  167. break
  168. current_frame = current_frame.f_back
  169. cleansed = {}
  170. if self.is_active(request) and sensitive_variables:
  171. if sensitive_variables == '__ALL__':
  172. # Cleanse all variables
  173. for name, value in tb_frame.f_locals.items():
  174. cleansed[name] = CLEANSED_SUBSTITUTE
  175. else:
  176. # Cleanse specified variables
  177. for name, value in tb_frame.f_locals.items():
  178. if name in sensitive_variables:
  179. value = CLEANSED_SUBSTITUTE
  180. else:
  181. value = self.cleanse_special_types(request, value)
  182. cleansed[name] = value
  183. else:
  184. # Potentially cleanse the request and any MultiValueDicts if they
  185. # are one of the frame variables.
  186. for name, value in tb_frame.f_locals.items():
  187. cleansed[name] = self.cleanse_special_types(request, value)
  188. if (tb_frame.f_code.co_name == 'sensitive_variables_wrapper'
  189. and 'sensitive_variables_wrapper' in tb_frame.f_locals):
  190. # For good measure, obfuscate the decorated function's arguments in
  191. # the sensitive_variables decorator's frame, in case the variables
  192. # associated with those arguments were meant to be obfuscated from
  193. # the decorated function's frame.
  194. cleansed['func_args'] = CLEANSED_SUBSTITUTE
  195. cleansed['func_kwargs'] = CLEANSED_SUBSTITUTE
  196. return cleansed.items()
  197. class ExceptionReporter(object):
  198. """
  199. A class to organize and coordinate reporting on exceptions.
  200. """
  201. def __init__(self, request, exc_type, exc_value, tb, is_email=False):
  202. self.request = request
  203. self.filter = get_exception_reporter_filter(self.request)
  204. self.exc_type = exc_type
  205. self.exc_value = exc_value
  206. self.tb = tb
  207. self.is_email = is_email
  208. self.template_info = None
  209. self.template_does_not_exist = False
  210. self.loader_debug_info = None
  211. # Handle deprecated string exceptions
  212. if isinstance(self.exc_type, six.string_types):
  213. self.exc_value = Exception('Deprecated String Exception: %r' % self.exc_type)
  214. self.exc_type = type(self.exc_value)
  215. def format_path_status(self, path):
  216. if not os.path.exists(path):
  217. return "File does not exist"
  218. if not os.path.isfile(path):
  219. return "Not a file"
  220. if not os.access(path, os.R_OK):
  221. return "File is not readable"
  222. return "File exists"
  223. def get_traceback_data(self):
  224. """Return a dictionary containing traceback information."""
  225. if self.exc_type and issubclass(self.exc_type, TemplateDoesNotExist):
  226. from django.template.loader import template_source_loaders
  227. self.template_does_not_exist = True
  228. self.loader_debug_info = []
  229. # If the template_source_loaders haven't been populated yet, you need
  230. # to provide an empty list for this for loop to not fail.
  231. if template_source_loaders is None:
  232. template_source_loaders = []
  233. for loader in template_source_loaders:
  234. try:
  235. source_list_func = loader.get_template_sources
  236. # NOTE: This assumes exc_value is the name of the template that
  237. # the loader attempted to load.
  238. template_list = [{
  239. 'name': t,
  240. 'status': self.format_path_status(t),
  241. } for t in source_list_func(str(self.exc_value))]
  242. except AttributeError:
  243. template_list = []
  244. loader_name = loader.__module__ + '.' + loader.__class__.__name__
  245. self.loader_debug_info.append({
  246. 'loader': loader_name,
  247. 'templates': template_list,
  248. })
  249. if (settings.TEMPLATE_DEBUG and
  250. hasattr(self.exc_value, 'django_template_source')):
  251. self.get_template_exception_info()
  252. frames = self.get_traceback_frames()
  253. for i, frame in enumerate(frames):
  254. if 'vars' in frame:
  255. frame['vars'] = [(k, force_escape(pprint(v))) for k, v in frame['vars']]
  256. frames[i] = frame
  257. unicode_hint = ''
  258. if self.exc_type and issubclass(self.exc_type, UnicodeError):
  259. start = getattr(self.exc_value, 'start', None)
  260. end = getattr(self.exc_value, 'end', None)
  261. if start is not None and end is not None:
  262. unicode_str = self.exc_value.args[1]
  263. unicode_hint = smart_text(unicode_str[max(start - 5, 0):min(end + 5, len(unicode_str))], 'ascii', errors='replace')
  264. from django import get_version
  265. c = {
  266. 'is_email': self.is_email,
  267. 'unicode_hint': unicode_hint,
  268. 'frames': frames,
  269. 'request': self.request,
  270. 'filtered_POST': self.filter.get_post_parameters(self.request),
  271. 'settings': get_safe_settings(),
  272. 'sys_executable': sys.executable,
  273. 'sys_version_info': '%d.%d.%d' % sys.version_info[0:3],
  274. 'server_time': datetime.datetime.now(),
  275. 'django_version_info': get_version(),
  276. 'sys_path': sys.path,
  277. 'template_info': self.template_info,
  278. 'template_does_not_exist': self.template_does_not_exist,
  279. 'loader_debug_info': self.loader_debug_info,
  280. }
  281. # Check whether exception info is available
  282. if self.exc_type:
  283. c['exception_type'] = self.exc_type.__name__
  284. if self.exc_value:
  285. c['exception_value'] = smart_text(self.exc_value, errors='replace')
  286. if frames:
  287. c['lastframe'] = frames[-1]
  288. return c
  289. def get_traceback_html(self):
  290. "Return HTML version of debug 500 HTTP error page."
  291. t = Template(TECHNICAL_500_TEMPLATE, name='Technical 500 template')
  292. c = Context(self.get_traceback_data(), use_l10n=False)
  293. return t.render(c)
  294. def get_traceback_text(self):
  295. "Return plain text version of debug 500 HTTP error page."
  296. t = Template(TECHNICAL_500_TEXT_TEMPLATE, name='Technical 500 template')
  297. c = Context(self.get_traceback_data(), autoescape=False, use_l10n=False)
  298. return t.render(c)
  299. def get_template_exception_info(self):
  300. origin, (start, end) = self.exc_value.django_template_source
  301. template_source = origin.reload()
  302. context_lines = 10
  303. line = 0
  304. upto = 0
  305. source_lines = []
  306. before = during = after = ""
  307. for num, next in enumerate(linebreak_iter(template_source)):
  308. if start >= upto and end <= next:
  309. line = num
  310. before = escape(template_source[upto:start])
  311. during = escape(template_source[start:end])
  312. after = escape(template_source[end:next])
  313. source_lines.append((num, escape(template_source[upto:next])))
  314. upto = next
  315. total = len(source_lines)
  316. top = max(1, line - context_lines)
  317. bottom = min(total, line + 1 + context_lines)
  318. # In some rare cases, exc_value.args might be empty.
  319. try:
  320. message = self.exc_value.args[0]
  321. except IndexError:
  322. message = '(Could not get exception message)'
  323. self.template_info = {
  324. 'message': message,
  325. 'source_lines': source_lines[top:bottom],
  326. 'before': before,
  327. 'during': during,
  328. 'after': after,
  329. 'top': top,
  330. 'bottom': bottom,
  331. 'total': total,
  332. 'line': line,
  333. 'name': origin.name,
  334. }
  335. def _get_lines_from_file(self, filename, lineno, context_lines, loader=None, module_name=None):
  336. """
  337. Returns context_lines before and after lineno from file.
  338. Returns (pre_context_lineno, pre_context, context_line, post_context).
  339. """
  340. source = None
  341. if loader is not None and hasattr(loader, "get_source"):
  342. try:
  343. source = loader.get_source(module_name)
  344. except ImportError:
  345. pass
  346. if source is not None:
  347. source = source.splitlines()
  348. if source is None:
  349. try:
  350. with open(filename, 'rb') as fp:
  351. source = fp.read().splitlines()
  352. except (OSError, IOError):
  353. pass
  354. if source is None:
  355. return None, [], None, []
  356. # If we just read the source from a file, or if the loader did not
  357. # apply tokenize.detect_encoding to decode the source into a Unicode
  358. # string, then we should do that ourselves.
  359. if isinstance(source[0], six.binary_type):
  360. encoding = 'ascii'
  361. for line in source[:2]:
  362. # File coding may be specified. Match pattern from PEP-263
  363. # (http://www.python.org/dev/peps/pep-0263/)
  364. match = re.search(br'coding[:=]\s*([-\w.]+)', line)
  365. if match:
  366. encoding = match.group(1).decode('ascii')
  367. break
  368. source = [six.text_type(sline, encoding, 'replace') for sline in source]
  369. lower_bound = max(0, lineno - context_lines)
  370. upper_bound = lineno + context_lines
  371. pre_context = source[lower_bound:lineno]
  372. context_line = source[lineno]
  373. post_context = source[lineno + 1:upper_bound]
  374. return lower_bound, pre_context, context_line, post_context
  375. def get_traceback_frames(self):
  376. frames = []
  377. tb = self.tb
  378. while tb is not None:
  379. # Support for __traceback_hide__ which is used by a few libraries
  380. # to hide internal frames.
  381. if tb.tb_frame.f_locals.get('__traceback_hide__'):
  382. tb = tb.tb_next
  383. continue
  384. filename = tb.tb_frame.f_code.co_filename
  385. function = tb.tb_frame.f_code.co_name
  386. lineno = tb.tb_lineno - 1
  387. loader = tb.tb_frame.f_globals.get('__loader__')
  388. module_name = tb.tb_frame.f_globals.get('__name__') or ''
  389. pre_context_lineno, pre_context, context_line, post_context = self._get_lines_from_file(filename, lineno, 7, loader, module_name)
  390. if pre_context_lineno is not None:
  391. frames.append({
  392. 'tb': tb,
  393. 'type': 'django' if module_name.startswith('django.') else 'user',
  394. 'filename': filename,
  395. 'function': function,
  396. 'lineno': lineno + 1,
  397. 'vars': self.filter.get_traceback_frame_variables(self.request, tb.tb_frame),
  398. 'id': id(tb),
  399. 'pre_context': pre_context,
  400. 'context_line': context_line,
  401. 'post_context': post_context,
  402. 'pre_context_lineno': pre_context_lineno + 1,
  403. })
  404. tb = tb.tb_next
  405. return frames
  406. def format_exception(self):
  407. """
  408. Return the same data as from traceback.format_exception.
  409. """
  410. import traceback
  411. frames = self.get_traceback_frames()
  412. tb = [(f['filename'], f['lineno'], f['function'], f['context_line']) for f in frames]
  413. list = ['Traceback (most recent call last):\n']
  414. list += traceback.format_list(tb)
  415. list += traceback.format_exception_only(self.exc_type, self.exc_value)
  416. return list
  417. def technical_404_response(request, exception):
  418. "Create a technical 404 error response. The exception should be the Http404."
  419. try:
  420. error_url = exception.args[0]['path']
  421. except (IndexError, TypeError, KeyError):
  422. error_url = request.path_info[1:] # Trim leading slash
  423. try:
  424. tried = exception.args[0]['tried']
  425. except (IndexError, TypeError, KeyError):
  426. tried = []
  427. else:
  428. if (not tried # empty URLconf
  429. or (request.path == '/'
  430. and len(tried) == 1 # default URLconf
  431. and len(tried[0]) == 1
  432. and getattr(tried[0][0], 'app_name', '') == getattr(tried[0][0], 'namespace', '') == 'admin')):
  433. return default_urlconf(request)
  434. urlconf = getattr(request, 'urlconf', settings.ROOT_URLCONF)
  435. if isinstance(urlconf, types.ModuleType):
  436. urlconf = urlconf.__name__
  437. t = Template(TECHNICAL_404_TEMPLATE, name='Technical 404 template')
  438. c = Context({
  439. 'urlconf': urlconf,
  440. 'root_urlconf': settings.ROOT_URLCONF,
  441. 'request_path': error_url,
  442. 'urlpatterns': tried,
  443. 'reason': force_bytes(exception, errors='replace'),
  444. 'request': request,
  445. 'settings': get_safe_settings(),
  446. })
  447. return HttpResponseNotFound(t.render(c), content_type='text/html')
  448. def default_urlconf(request):
  449. "Create an empty URLconf 404 error response."
  450. t = Template(DEFAULT_URLCONF_TEMPLATE, name='Default URLconf template')
  451. c = Context({})
  452. return HttpResponse(t.render(c), content_type='text/html')
  453. #
  454. # Templates are embedded in the file so that we know the error handler will
  455. # always work even if the template loader is broken.
  456. #
  457. TECHNICAL_500_TEMPLATE = """
  458. <!DOCTYPE html>
  459. <html lang="en">
  460. <head>
  461. <meta http-equiv="content-type" content="text/html; charset=utf-8">
  462. <meta name="robots" content="NONE,NOARCHIVE">
  463. <title>{% if exception_type %}{{ exception_type }}{% else %}Report{% endif %}{% if request %} at {{ request.path_info|escape }}{% endif %}</title>
  464. <style type="text/css">
  465. html * { padding:0; margin:0; }
  466. body * { padding:10px 20px; }
  467. body * * { padding:0; }
  468. body { font:small sans-serif; }
  469. body>div { border-bottom:1px solid #ddd; }
  470. h1 { font-weight:normal; }
  471. h2 { margin-bottom:.8em; }
  472. h2 span { font-size:80%; color:#666; font-weight:normal; }
  473. h3 { margin:1em 0 .5em 0; }
  474. h4 { margin:0 0 .5em 0; font-weight: normal; }
  475. code, pre { font-size: 100%; white-space: pre-wrap; }
  476. table { border:1px solid #ccc; border-collapse: collapse; width:100%; background:white; }
  477. tbody td, tbody th { vertical-align:top; padding:2px 3px; }
  478. thead th { padding:1px 6px 1px 3px; background:#fefefe; text-align:left; font-weight:normal; font-size:11px; border:1px solid #ddd; }
  479. tbody th { width:12em; text-align:right; color:#666; padding-right:.5em; }
  480. table.vars { margin:5px 0 2px 40px; }
  481. table.vars td, table.req td { font-family:monospace; }
  482. table td.code { width:100%; }
  483. table td.code pre { overflow:hidden; }
  484. table.source th { color:#666; }
  485. table.source td { font-family:monospace; white-space:pre; border-bottom:1px solid #eee; }
  486. ul.traceback { list-style-type:none; color: #222; }
  487. ul.traceback li.frame { padding-bottom:1em; color:#666; }
  488. ul.traceback li.user { background-color:#e0e0e0; color:#000 }
  489. div.context { padding:10px 0; overflow:hidden; }
  490. div.context ol { padding-left:30px; margin:0 10px; list-style-position: inside; }
  491. div.context ol li { font-family:monospace; white-space:pre; color:#777; cursor:pointer; }
  492. div.context ol li pre { display:inline; }
  493. div.context ol.context-line li { color:#505050; background-color:#dfdfdf; }
  494. div.context ol.context-line li span { position:absolute; right:32px; }
  495. .user div.context ol.context-line li { background-color:#bbb; color:#000; }
  496. .user div.context ol li { color:#666; }
  497. div.commands { margin-left: 40px; }
  498. div.commands a { color:#555; text-decoration:none; }
  499. .user div.commands a { color: black; }
  500. #summary { background: #ffc; }
  501. #summary h2 { font-weight: normal; color: #666; }
  502. #explanation { background:#eee; }
  503. #template, #template-not-exist { background:#f6f6f6; }
  504. #template-not-exist ul { margin: 0 0 0 20px; }
  505. #unicode-hint { background:#eee; }
  506. #traceback { background:#eee; }
  507. #requestinfo { background:#f6f6f6; padding-left:120px; }
  508. #summary table { border:none; background:transparent; }
  509. #requestinfo h2, #requestinfo h3 { position:relative; margin-left:-100px; }
  510. #requestinfo h3 { margin-bottom:-1em; }
  511. .error { background: #ffc; }
  512. .specific { color:#cc3300; font-weight:bold; }
  513. h2 span.commands { font-size:.7em;}
  514. span.commands a:link {color:#5E5694;}
  515. pre.exception_value { font-family: sans-serif; color: #666; font-size: 1.5em; margin: 10px 0 10px 0; }
  516. </style>
  517. {% if not is_email %}
  518. <script type="text/javascript">
  519. //<!--
  520. function getElementsByClassName(oElm, strTagName, strClassName){
  521. // Written by Jonathan Snook, http://www.snook.ca/jon; Add-ons by Robert Nyman, http://www.robertnyman.com
  522. var arrElements = (strTagName == "*" && document.all)? document.all :
  523. oElm.getElementsByTagName(strTagName);
  524. var arrReturnElements = new Array();
  525. strClassName = strClassName.replace(/\-/g, "\\-");
  526. var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
  527. var oElement;
  528. for(var i=0; i<arrElements.length; i++){
  529. oElement = arrElements[i];
  530. if(oRegExp.test(oElement.className)){
  531. arrReturnElements.push(oElement);
  532. }
  533. }
  534. return (arrReturnElements)
  535. }
  536. function hideAll(elems) {
  537. for (var e = 0; e < elems.length; e++) {
  538. elems[e].style.display = 'none';
  539. }
  540. }
  541. window.onload = function() {
  542. hideAll(getElementsByClassName(document, 'table', 'vars'));
  543. hideAll(getElementsByClassName(document, 'ol', 'pre-context'));
  544. hideAll(getElementsByClassName(document, 'ol', 'post-context'));
  545. hideAll(getElementsByClassName(document, 'div', 'pastebin'));
  546. }
  547. function toggle() {
  548. for (var i = 0; i < arguments.length; i++) {
  549. var e = document.getElementById(arguments[i]);
  550. if (e) {
  551. e.style.display = e.style.display == 'none' ? 'block': 'none';
  552. }
  553. }
  554. return false;
  555. }
  556. function varToggle(link, id) {
  557. toggle('v' + id);
  558. var s = link.getElementsByTagName('span')[0];
  559. var uarr = String.fromCharCode(0x25b6);
  560. var darr = String.fromCharCode(0x25bc);
  561. s.innerHTML = s.innerHTML == uarr ? darr : uarr;
  562. return false;
  563. }
  564. function switchPastebinFriendly(link) {
  565. s1 = "Switch to copy-and-paste view";
  566. s2 = "Switch back to interactive view";
  567. link.innerHTML = link.innerHTML == s1 ? s2: s1;
  568. toggle('browserTraceback', 'pastebinTraceback');
  569. return false;
  570. }
  571. //-->
  572. </script>
  573. {% endif %}
  574. </head>
  575. <body>
  576. <div id="summary">
  577. <h1>{% if exception_type %}{{ exception_type }}{% else %}Report{% endif %}{% if request %} at {{ request.path_info|escape }}{% endif %}</h1>
  578. <pre class="exception_value">{% if exception_value %}{{ exception_value|force_escape }}{% else %}No exception message supplied{% endif %}</pre>
  579. <table class="meta">
  580. {% if request %}
  581. <tr>
  582. <th>Request Method:</th>
  583. <td>{{ request.META.REQUEST_METHOD }}</td>
  584. </tr>
  585. <tr>
  586. <th>Request URL:</th>
  587. <td>{{ request.build_absolute_uri|escape }}</td>
  588. </tr>
  589. {% endif %}
  590. <tr>
  591. <th>Django Version:</th>
  592. <td>{{ django_version_info }}</td>
  593. </tr>
  594. {% if exception_type %}
  595. <tr>
  596. <th>Exception Type:</th>
  597. <td>{{ exception_type }}</td>
  598. </tr>
  599. {% endif %}
  600. {% if exception_type and exception_value %}
  601. <tr>
  602. <th>Exception Value:</th>
  603. <td><pre>{{ exception_value|force_escape }}</pre></td>
  604. </tr>
  605. {% endif %}
  606. {% if lastframe %}
  607. <tr>
  608. <th>Exception Location:</th>
  609. <td>{{ lastframe.filename|escape }} in {{ lastframe.function|escape }}, line {{ lastframe.lineno }}</td>
  610. </tr>
  611. {% endif %}
  612. <tr>
  613. <th>Python Executable:</th>
  614. <td>{{ sys_executable|escape }}</td>
  615. </tr>
  616. <tr>
  617. <th>Python Version:</th>
  618. <td>{{ sys_version_info }}</td>
  619. </tr>
  620. <tr>
  621. <th>Python Path:</th>
  622. <td><pre>{{ sys_path|pprint }}</pre></td>
  623. </tr>
  624. <tr>
  625. <th>Server time:</th>
  626. <td>{{server_time|date:"r"}}</td>
  627. </tr>
  628. </table>
  629. </div>
  630. {% if unicode_hint %}
  631. <div id="unicode-hint">
  632. <h2>Unicode error hint</h2>
  633. <p>The string that could not be encoded/decoded was: <strong>{{ unicode_hint|force_escape }}</strong></p>
  634. </div>
  635. {% endif %}
  636. {% if template_does_not_exist %}
  637. <div id="template-not-exist">
  638. <h2>Template-loader postmortem</h2>
  639. {% if loader_debug_info %}
  640. <p>Django tried loading these templates, in this order:</p>
  641. <ul>
  642. {% for loader in loader_debug_info %}
  643. <li>Using loader <code>{{ loader.loader }}</code>:
  644. <ul>
  645. {% for t in loader.templates %}<li><code>{{ t.name }}</code> ({{ t.status }})</li>{% endfor %}
  646. </ul>
  647. </li>
  648. {% endfor %}
  649. </ul>
  650. {% else %}
  651. <p>Django couldn't find any templates because your <code>TEMPLATE_LOADERS</code> setting is empty!</p>
  652. {% endif %}
  653. </div>
  654. {% endif %}
  655. {% if template_info %}
  656. <div id="template">
  657. <h2>Error during template rendering</h2>
  658. <p>In template <code>{{ template_info.name }}</code>, error at line <strong>{{ template_info.line }}</strong></p>
  659. <h3>{{ template_info.message }}</h3>
  660. <table class="source{% if template_info.top %} cut-top{% endif %}{% ifnotequal template_info.bottom template_info.total %} cut-bottom{% endifnotequal %}">
  661. {% for source_line in template_info.source_lines %}
  662. {% ifequal source_line.0 template_info.line %}
  663. <tr class="error"><th>{{ source_line.0 }}</th>
  664. <td>{{ template_info.before }}<span class="specific">{{ template_info.during }}</span>{{ template_info.after }}</td></tr>
  665. {% else %}
  666. <tr><th>{{ source_line.0 }}</th>
  667. <td>{{ source_line.1 }}</td></tr>
  668. {% endifequal %}
  669. {% endfor %}
  670. </table>
  671. </div>
  672. {% endif %}
  673. {% if frames %}
  674. <div id="traceback">
  675. <h2>Traceback <span class="commands">{% if not is_email %}<a href="#" onclick="return switchPastebinFriendly(this);">Switch to copy-and-paste view</a></span>{% endif %}</h2>
  676. {% autoescape off %}
  677. <div id="browserTraceback">
  678. <ul class="traceback">
  679. {% for frame in frames %}
  680. <li class="frame {{ frame.type }}">
  681. <code>{{ frame.filename|escape }}</code> in <code>{{ frame.function|escape }}</code>
  682. {% if frame.context_line %}
  683. <div class="context" id="c{{ frame.id }}">
  684. {% if frame.pre_context and not is_email %}
  685. <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 }}')"><pre>{{ line|escape }}</pre></li>{% endfor %}</ol>
  686. {% endif %}
  687. <ol start="{{ frame.lineno }}" class="context-line"><li onclick="toggle('pre{{ frame.id }}', 'post{{ frame.id }}')"><pre>{{ frame.context_line|escape }}</pre>{% if not is_email %} <span>...</span>{% endif %}</li></ol>
  688. {% if frame.post_context and not is_email %}
  689. <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 }}')"><pre>{{ line|escape }}</pre></li>{% endfor %}</ol>
  690. {% endif %}
  691. </div>
  692. {% endif %}
  693. {% if frame.vars %}
  694. <div class="commands">
  695. {% if is_email %}
  696. <h2>Local Vars</h2>
  697. {% else %}
  698. <a href="#" onclick="return varToggle(this, '{{ frame.id }}')"><span>&#x25b6;</span> Local vars</a>
  699. {% endif %}
  700. </div>
  701. <table class="vars" id="v{{ frame.id }}">
  702. <thead>
  703. <tr>
  704. <th>Variable</th>
  705. <th>Value</th>
  706. </tr>
  707. </thead>
  708. <tbody>
  709. {% for var in frame.vars|dictsort:"0" %}
  710. <tr>
  711. <td>{{ var.0|force_escape }}</td>
  712. <td class="code"><pre>{{ var.1 }}</pre></td>
  713. </tr>
  714. {% endfor %}
  715. </tbody>
  716. </table>
  717. {% endif %}
  718. </li>
  719. {% endfor %}
  720. </ul>
  721. </div>
  722. {% endautoescape %}
  723. <form action="http://dpaste.com/" name="pasteform" id="pasteform" method="post">
  724. {% if not is_email %}
  725. <div id="pastebinTraceback" class="pastebin">
  726. <input type="hidden" name="language" value="PythonConsole">
  727. <input type="hidden" name="title" value="{{ exception_type|escape }}{% if request %} at {{ request.path_info|escape }}{% endif %}">
  728. <input type="hidden" name="source" value="Django Dpaste Agent">
  729. <input type="hidden" name="poster" value="Django">
  730. <textarea name="content" id="traceback_area" cols="140" rows="25">
  731. Environment:
  732. {% if request %}
  733. Request Method: {{ request.META.REQUEST_METHOD }}
  734. Request URL: {{ request.build_absolute_uri|escape }}
  735. {% endif %}
  736. Django Version: {{ django_version_info }}
  737. Python Version: {{ sys_version_info }}
  738. Installed Applications:
  739. {{ settings.INSTALLED_APPS|pprint }}
  740. Installed Middleware:
  741. {{ settings.MIDDLEWARE_CLASSES|pprint }}
  742. {% if template_does_not_exist %}Template Loader Error:
  743. {% if loader_debug_info %}Django tried loading these templates, in this order:
  744. {% for loader in loader_debug_info %}Using loader {{ loader.loader }}:
  745. {% for t in loader.templates %}{{ t.name }} ({{ t.status }})
  746. {% endfor %}{% endfor %}
  747. {% else %}Django couldn't find any templates because your TEMPLATE_LOADERS setting is empty!
  748. {% endif %}
  749. {% endif %}{% if template_info %}
  750. Template error:
  751. In template {{ template_info.name }}, error at line {{ template_info.line }}
  752. {{ template_info.message }}{% for source_line in template_info.source_lines %}{% ifequal source_line.0 template_info.line %}
  753. {{ source_line.0 }} : {{ template_info.before }} {{ template_info.during }} {{ template_info.after }}
  754. {% else %}
  755. {{ source_line.0 }} : {{ source_line.1 }}
  756. {% endifequal %}{% endfor %}{% endif %}
  757. Traceback:
  758. {% for frame in frames %}File "{{ frame.filename|escape }}" in {{ frame.function|escape }}
  759. {% if frame.context_line %} {{ frame.lineno }}. {{ frame.context_line|escape }}{% endif %}
  760. {% endfor %}
  761. Exception Type: {{ exception_type|escape }}{% if request %} at {{ request.path_info|escape }}{% endif %}
  762. Exception Value: {{ exception_value|force_escape }}
  763. </textarea>
  764. <br><br>
  765. <input type="submit" value="Share this traceback on a public Web site">
  766. </div>
  767. </form>
  768. </div>
  769. {% endif %}
  770. {% endif %}
  771. <div id="requestinfo">
  772. <h2>Request information</h2>
  773. {% if request %}
  774. <h3 id="get-info">GET</h3>
  775. {% if request.GET %}
  776. <table class="req">
  777. <thead>
  778. <tr>
  779. <th>Variable</th>
  780. <th>Value</th>
  781. </tr>
  782. </thead>
  783. <tbody>
  784. {% for var in request.GET.items %}
  785. <tr>
  786. <td>{{ var.0 }}</td>
  787. <td class="code"><pre>{{ var.1|pprint }}</pre></td>
  788. </tr>
  789. {% endfor %}
  790. </tbody>
  791. </table>
  792. {% else %}
  793. <p>No GET data</p>
  794. {% endif %}
  795. <h3 id="post-info">POST</h3>
  796. {% if filtered_POST %}
  797. <table class="req">
  798. <thead>
  799. <tr>
  800. <th>Variable</th>
  801. <th>Value</th>
  802. </tr>
  803. </thead>
  804. <tbody>
  805. {% for var in filtered_POST.items %}
  806. <tr>
  807. <td>{{ var.0 }}</td>
  808. <td class="code"><pre>{{ var.1|pprint }}</pre></td>
  809. </tr>
  810. {% endfor %}
  811. </tbody>
  812. </table>
  813. {% else %}
  814. <p>No POST data</p>
  815. {% endif %}
  816. <h3 id="files-info">FILES</h3>
  817. {% if request.FILES %}
  818. <table class="req">
  819. <thead>
  820. <tr>
  821. <th>Variable</th>
  822. <th>Value</th>
  823. </tr>
  824. </thead>
  825. <tbody>
  826. {% for var in request.FILES.items %}
  827. <tr>
  828. <td>{{ var.0 }}</td>
  829. <td class="code"><pre>{{ var.1|pprint }}</pre></td>
  830. </tr>
  831. {% endfor %}
  832. </tbody>
  833. </table>
  834. {% else %}
  835. <p>No FILES data</p>
  836. {% endif %}
  837. <h3 id="cookie-info">COOKIES</h3>
  838. {% if request.COOKIES %}
  839. <table class="req">
  840. <thead>
  841. <tr>
  842. <th>Variable</th>
  843. <th>Value</th>
  844. </tr>
  845. </thead>
  846. <tbody>
  847. {% for var in request.COOKIES.items %}
  848. <tr>
  849. <td>{{ var.0 }}</td>
  850. <td class="code"><pre>{{ var.1|pprint }}</pre></td>
  851. </tr>
  852. {% endfor %}
  853. </tbody>
  854. </table>
  855. {% else %}
  856. <p>No cookie data</p>
  857. {% endif %}
  858. <h3 id="meta-info">META</h3>
  859. <table class="req">
  860. <thead>
  861. <tr>
  862. <th>Variable</th>
  863. <th>Value</th>
  864. </tr>
  865. </thead>
  866. <tbody>
  867. {% for var in request.META.items|dictsort:"0" %}
  868. <tr>
  869. <td>{{ var.0 }}</td>
  870. <td class="code"><pre>{{ var.1|pprint }}</pre></td>
  871. </tr>
  872. {% endfor %}
  873. </tbody>
  874. </table>
  875. {% else %}
  876. <p>Request data not supplied</p>
  877. {% endif %}
  878. <h3 id="settings-info">Settings</h3>
  879. <h4>Using settings module <code>{{ settings.SETTINGS_MODULE }}</code></h4>
  880. <table class="req">
  881. <thead>
  882. <tr>
  883. <th>Setting</th>
  884. <th>Value</th>
  885. </tr>
  886. </thead>
  887. <tbody>
  888. {% for var in settings.items|dictsort:"0" %}
  889. <tr>
  890. <td>{{ var.0 }}</td>
  891. <td class="code"><pre>{{ var.1|pprint }}</pre></td>
  892. </tr>
  893. {% endfor %}
  894. </tbody>
  895. </table>
  896. </div>
  897. {% if not is_email %}
  898. <div id="explanation">
  899. <p>
  900. You're seeing this error because you have <code>DEBUG = True</code> in your
  901. Django settings file. Change that to <code>False</code>, and Django will
  902. display a standard 500 page.
  903. </p>
  904. </div>
  905. {% endif %}
  906. </body>
  907. </html>
  908. """
  909. TECHNICAL_500_TEXT_TEMPLATE = """{% load firstof from future %}{% firstof exception_type 'Report' %}{% if request %} at {{ request.path_info }}{% endif %}
  910. {% firstof exception_value 'No exception message supplied' %}
  911. {% if request %}
  912. Request Method: {{ request.META.REQUEST_METHOD }}
  913. Request URL: {{ request.build_absolute_uri }}{% endif %}
  914. Django Version: {{ django_version_info }}
  915. Python Executable: {{ sys_executable }}
  916. Python Version: {{ sys_version_info }}
  917. Python Path: {{ sys_path }}
  918. Server time: {{server_time|date:"r"}}
  919. Installed Applications:
  920. {{ settings.INSTALLED_APPS|pprint }}
  921. Installed Middleware:
  922. {{ settings.MIDDLEWARE_CLASSES|pprint }}
  923. {% if template_does_not_exist %}Template loader Error:
  924. {% if loader_debug_info %}Django tried loading these templates, in this order:
  925. {% for loader in loader_debug_info %}Using loader {{ loader.loader }}:
  926. {% for t in loader.templates %}{{ t.name }} ({{ t.status }})
  927. {% endfor %}{% endfor %}
  928. {% else %}Django couldn't find any templates because your TEMPLATE_LOADERS setting is empty!
  929. {% endif %}
  930. {% endif %}{% if template_info %}
  931. Template error:
  932. In template {{ template_info.name }}, error at line {{ template_info.line }}
  933. {{ template_info.message }}{% for source_line in template_info.source_lines %}{% ifequal source_line.0 template_info.line %}
  934. {{ source_line.0 }} : {{ template_info.before }} {{ template_info.during }} {{ template_info.after }}
  935. {% else %}
  936. {{ source_line.0 }} : {{ source_line.1 }}
  937. {% endifequal %}{% endfor %}{% endif %}{% if frames %}
  938. Traceback:
  939. {% for frame in frames %}File "{{ frame.filename }}" in {{ frame.function }}
  940. {% if frame.context_line %} {{ frame.lineno }}. {{ frame.context_line }}{% endif %}
  941. {% endfor %}
  942. {% if exception_type %}Exception Type: {{ exception_type }}{% if request %} at {{ request.path_info }}{% endif %}
  943. {% if exception_value %}Exception Value: {{ exception_value }}{% endif %}{% endif %}{% endif %}
  944. {% if request %}Request information:
  945. GET:{% for k, v in request.GET.items %}
  946. {{ k }} = {{ v|stringformat:"r" }}{% empty %} No GET data{% endfor %}
  947. POST:{% for k, v in filtered_POST.items %}
  948. {{ k }} = {{ v|stringformat:"r" }}{% empty %} No POST data{% endfor %}
  949. FILES:{% for k, v in request.FILES.items %}
  950. {{ k }} = {{ v|stringformat:"r" }}{% empty %} No FILES data{% endfor %}
  951. COOKIES:{% for k, v in request.COOKIES.items %}
  952. {{ k }} = {{ v|stringformat:"r" }}{% empty %} No cookie data{% endfor %}
  953. META:{% for k, v in request.META.items|dictsort:"0" %}
  954. {{ k }} = {{ v|stringformat:"r" }}{% endfor %}
  955. {% else %}Request data not supplied
  956. {% endif %}
  957. Settings:
  958. Using settings module {{ settings.SETTINGS_MODULE }}{% for k, v in settings.items|dictsort:"0" %}
  959. {{ k }} = {{ v|stringformat:"r" }}{% endfor %}
  960. You're seeing this error because you have DEBUG = True in your
  961. Django settings file. Change that to False, and Django will
  962. display a standard 500 page.
  963. """
  964. TECHNICAL_404_TEMPLATE = """
  965. <!DOCTYPE html>
  966. <html lang="en">
  967. <head>
  968. <meta http-equiv="content-type" content="text/html; charset=utf-8">
  969. <title>Page not found at {{ request.path_info|escape }}</title>
  970. <meta name="robots" content="NONE,NOARCHIVE">
  971. <style type="text/css">
  972. html * { padding:0; margin:0; }
  973. body * { padding:10px 20px; }
  974. body * * { padding:0; }
  975. body { font:small sans-serif; background:#eee; }
  976. body>div { border-bottom:1px solid #ddd; }
  977. h1 { font-weight:normal; margin-bottom:.4em; }
  978. h1 span { font-size:60%; color:#666; font-weight:normal; }
  979. table { border:none; border-collapse: collapse; width:100%; }
  980. td, th { vertical-align:top; padding:2px 3px; }
  981. th { width:12em; text-align:right; color:#666; padding-right:.5em; }
  982. #info { background:#f6f6f6; }
  983. #info ol { margin: 0.5em 4em; }
  984. #info ol li { font-family: monospace; }
  985. #summary { background: #ffc; }
  986. #explanation { background:#eee; border-bottom: 0px none; }
  987. </style>
  988. </head>
  989. <body>
  990. <div id="summary">
  991. <h1>Page not found <span>(404)</span></h1>
  992. <table class="meta">
  993. <tr>
  994. <th>Request Method:</th>
  995. <td>{{ request.META.REQUEST_METHOD }}</td>
  996. </tr>
  997. <tr>
  998. <th>Request URL:</th>
  999. <td>{{ request.build_absolute_uri|escape }}</td>
  1000. </tr>
  1001. </table>
  1002. </div>
  1003. <div id="info">
  1004. {% if urlpatterns %}
  1005. <p>
  1006. Using the URLconf defined in <code>{{ urlconf }}</code>,
  1007. Django tried these URL patterns, in this order:
  1008. </p>
  1009. <ol>
  1010. {% for pattern in urlpatterns %}
  1011. <li>
  1012. {% for pat in pattern %}
  1013. {{ pat.regex.pattern }}
  1014. {% if forloop.last and pat.name %}[name='{{ pat.name }}']{% endif %}
  1015. {% endfor %}
  1016. </li>
  1017. {% endfor %}
  1018. </ol>
  1019. <p>The current URL, <code>{{ request_path|escape }}</code>, didn't match any of these.</p>
  1020. {% else %}
  1021. <p>{{ reason }}</p>
  1022. {% endif %}
  1023. </div>
  1024. <div id="explanation">
  1025. <p>
  1026. You're seeing this error because you have <code>DEBUG = True</code> in
  1027. your Django settings file. Change that to <code>False</code>, and Django
  1028. will display a standard 404 page.
  1029. </p>
  1030. </div>
  1031. </body>
  1032. </html>
  1033. """
  1034. DEFAULT_URLCONF_TEMPLATE = """
  1035. <!DOCTYPE html>
  1036. <html lang="en"><head>
  1037. <meta http-equiv="content-type" content="text/html; charset=utf-8">
  1038. <meta name="robots" content="NONE,NOARCHIVE"><title>Welcome to Django</title>
  1039. <style type="text/css">
  1040. html * { padding:0; margin:0; }
  1041. body * { padding:10px 20px; }
  1042. body * * { padding:0; }
  1043. body { font:small sans-serif; }
  1044. body>div { border-bottom:1px solid #ddd; }
  1045. h1 { font-weight:normal; }
  1046. h2 { margin-bottom:.8em; }
  1047. h2 span { font-size:80%; color:#666; font-weight:normal; }
  1048. h3 { margin:1em 0 .5em 0; }
  1049. h4 { margin:0 0 .5em 0; font-weight: normal; }
  1050. table { border:1px solid #ccc; border-collapse: collapse; width:100%; background:white; }
  1051. tbody td, tbody th { vertical-align:top; padding:2px 3px; }
  1052. thead th { padding:1px 6px 1px 3px; background:#fefefe; text-align:left; font-weight:normal; font-size:11px; border:1px solid #ddd; }
  1053. tbody th { width:12em; text-align:right; color:#666; padding-right:.5em; }
  1054. #summary { background: #e0ebff; }
  1055. #summary h2 { font-weight: normal; color: #666; }
  1056. #explanation { background:#eee; }
  1057. #instructions { background:#f6f6f6; }
  1058. #summary table { border:none; background:transparent; }
  1059. </style>
  1060. </head>
  1061. <body>
  1062. <div id="summary">
  1063. <h1>It worked!</h1>
  1064. <h2>Congratulations on your first Django-powered page.</h2>
  1065. </div>
  1066. <div id="instructions">
  1067. <p>
  1068. Of course, you haven't actually done any work yet.
  1069. Next, start your first app by running <code>python manage.py startapp [app_label]</code>.
  1070. </p>
  1071. </div>
  1072. <div id="explanation">
  1073. <p>
  1074. You're seeing this message because you have <code>DEBUG = True</code> in your
  1075. Django settings file and you haven't configured any URLs. Get to work!
  1076. </p>
  1077. </div>
  1078. </body></html>
  1079. """