debug.py 46 KB

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