import os import re import sys import datetime from django.conf import settings from django.template import Template, Context, TemplateDoesNotExist from django.utils.html import escape from django.utils.importlib import import_module from django.http import HttpResponse, HttpResponseServerError, HttpResponseNotFound from django.utils.encoding import smart_unicode, smart_str HIDDEN_SETTINGS = re.compile('SECRET|PASSWORD|PROFANITIES_LIST') def linebreak_iter(template_source): yield 0 p = template_source.find('\n') while p >= 0: yield p+1 p = template_source.find('\n', p+1) yield len(template_source) + 1 def get_safe_settings(): "Returns a dictionary of the settings module, with sensitive settings blurred out." settings_dict = {} for k in dir(settings): if k.isupper(): if HIDDEN_SETTINGS.search(k): settings_dict[k] = '********************' else: settings_dict[k] = getattr(settings, k) return settings_dict def technical_500_response(request, exc_type, exc_value, tb): """ Create a technical server error response. The last three arguments are the values returned from sys.exc_info() and friends. """ reporter = ExceptionReporter(request, exc_type, exc_value, tb) html = reporter.get_traceback_html() return HttpResponseServerError(html, mimetype='text/html') class ExceptionReporter: """ A class to organize and coordinate reporting on exceptions. """ def __init__(self, request, exc_type, exc_value, tb): self.request = request self.exc_type = exc_type self.exc_value = exc_value self.tb = tb self.template_info = None self.template_does_not_exist = False self.loader_debug_info = None # Handle deprecated string exceptions if isinstance(self.exc_type, basestring): self.exc_value = Exception('Deprecated String Exception: %r' % self.exc_type) self.exc_type = type(self.exc_value) def get_traceback_html(self): "Return HTML code for traceback." if issubclass(self.exc_type, TemplateDoesNotExist): from django.template.loader import template_source_loaders self.template_does_not_exist = True self.loader_debug_info = [] for loader in template_source_loaders: try: module = import_module(loader.__module__) source_list_func = module.get_template_sources # NOTE: This assumes exc_value is the name of the template that # the loader attempted to load. template_list = [{'name': t, 'exists': os.path.exists(t)} \ for t in source_list_func(str(self.exc_value))] except (ImportError, AttributeError): template_list = [] if hasattr(loader, '__class__'): loader_name = loader.__module__ + '.' + loader.__class__.__name__ else: loader_name = loader.__module__ + '.' + loader.__name__ self.loader_debug_info.append({ 'loader': loader_name, 'templates': template_list, }) if settings.TEMPLATE_DEBUG and hasattr(self.exc_value, 'source'): self.get_template_exception_info() frames = self.get_traceback_frames() unicode_hint = '' if issubclass(self.exc_type, UnicodeError): start = getattr(self.exc_value, 'start', None) end = getattr(self.exc_value, 'end', None) if start is not None and end is not None: unicode_str = self.exc_value.args[1] unicode_hint = smart_unicode(unicode_str[max(start-5, 0):min(end+5, len(unicode_str))], 'ascii', errors='replace') from django import get_version t = Template(TECHNICAL_500_TEMPLATE, name='Technical 500 template') c = Context({ 'exception_type': self.exc_type.__name__, 'exception_value': smart_unicode(self.exc_value, errors='replace'), 'unicode_hint': unicode_hint, 'frames': frames, 'lastframe': frames[-1], 'request': self.request, 'settings': get_safe_settings(), 'sys_executable': sys.executable, 'sys_version_info': '%d.%d.%d' % sys.version_info[0:3], 'server_time': datetime.datetime.now(), 'django_version_info': get_version(), 'sys_path' : sys.path, 'template_info': self.template_info, 'template_does_not_exist': self.template_does_not_exist, 'loader_debug_info': self.loader_debug_info, }) return t.render(c) def get_template_exception_info(self): origin, (start, end) = self.exc_value.source template_source = origin.reload() context_lines = 10 line = 0 upto = 0 source_lines = [] before = during = after = "" for num, next in enumerate(linebreak_iter(template_source)): if start >= upto and end <= next: line = num before = escape(template_source[upto:start]) during = escape(template_source[start:end]) after = escape(template_source[end:next]) source_lines.append( (num, escape(template_source[upto:next])) ) upto = next total = len(source_lines) top = max(1, line - context_lines) bottom = min(total, line + 1 + context_lines) self.template_info = { 'message': self.exc_value.args[0], 'source_lines': source_lines[top:bottom], 'before': before, 'during': during, 'after': after, 'top': top, 'bottom': bottom, 'total': total, 'line': line, 'name': origin.name, } def _get_lines_from_file(self, filename, lineno, context_lines, loader=None, module_name=None): """ Returns context_lines before and after lineno from file. Returns (pre_context_lineno, pre_context, context_line, post_context). """ source = None if loader is not None and hasattr(loader, "get_source"): source = loader.get_source(module_name) if source is not None: source = source.splitlines() if source is None: try: f = open(filename) try: source = f.readlines() finally: f.close() except (OSError, IOError): pass if source is None: return None, [], None, [] encoding = 'ascii' for line in source[:2]: # File coding may be specified. Match pattern from PEP-263 # (http://www.python.org/dev/peps/pep-0263/) match = re.search(r'coding[:=]\s*([-\w.]+)', line) if match: encoding = match.group(1) break source = [unicode(sline, encoding, 'replace') for sline in source] lower_bound = max(0, lineno - context_lines) upper_bound = lineno + context_lines pre_context = [line.strip('\n') for line in source[lower_bound:lineno]] context_line = source[lineno].strip('\n') post_context = [line.strip('\n') for line in source[lineno+1:upper_bound]] return lower_bound, pre_context, context_line, post_context def get_traceback_frames(self): frames = [] tb = self.tb while tb is not None: # support for __traceback_hide__ which is used by a few libraries # to hide internal frames. if tb.tb_frame.f_locals.get('__traceback_hide__'): tb = tb.tb_next continue filename = tb.tb_frame.f_code.co_filename function = tb.tb_frame.f_code.co_name lineno = tb.tb_lineno - 1 loader = tb.tb_frame.f_globals.get('__loader__') module_name = tb.tb_frame.f_globals.get('__name__') pre_context_lineno, pre_context, context_line, post_context = self._get_lines_from_file(filename, lineno, 7, loader, module_name) if pre_context_lineno is not None: frames.append({ 'tb': tb, 'filename': filename, 'function': function, 'lineno': lineno + 1, 'vars': tb.tb_frame.f_locals.items(), 'id': id(tb), 'pre_context': pre_context, 'context_line': context_line, 'post_context': post_context, 'pre_context_lineno': pre_context_lineno + 1, }) tb = tb.tb_next if not frames: frames = [{ 'filename': '<unknown>', 'function': '?', 'lineno': '?', 'context_line': '???', }] return frames def format_exception(self): """ Return the same data as from traceback.format_exception. """ import traceback frames = self.get_traceback_frames() tb = [ (f['filename'], f['lineno'], f['function'], f['context_line']) for f in frames ] list = ['Traceback (most recent call last):\n'] list += traceback.format_list(tb) list += traceback.format_exception_only(self.exc_type, self.exc_value) return list def technical_404_response(request, exception): "Create a technical 404 error response. The exception should be the Http404." try: tried = exception.args[0]['tried'] except (IndexError, TypeError): tried = [] else: if not tried: # tried exists but is an empty list. The URLconf must've been empty. return empty_urlconf(request) t = Template(TECHNICAL_404_TEMPLATE, name='Technical 404 template') c = Context({ 'root_urlconf': settings.ROOT_URLCONF, 'request_path': request.path_info[1:], # Trim leading slash 'urlpatterns': tried, 'reason': smart_str(exception, errors='replace'), 'request': request, 'settings': get_safe_settings(), }) return HttpResponseNotFound(t.render(c), mimetype='text/html') def empty_urlconf(request): "Create an empty URLconf 404 error response." t = Template(EMPTY_URLCONF_TEMPLATE, name='Empty URLConf template') c = Context({ 'project_name': settings.SETTINGS_MODULE.split('.')[0] }) return HttpResponse(t.render(c), mimetype='text/html') # # Templates are embedded in the file so that we know the error handler will # always work even if the template loader is broken. # TECHNICAL_500_TEMPLATE = """
{{ exception_value|escape }}
Request Method: | {{ request.META.REQUEST_METHOD }} |
---|---|
Request URL: | {{ request.build_absolute_uri|escape }} |
Exception Type: | {{ exception_type }} |
Exception Value: | {{ exception_value|escape }} |
Exception Location: | {{ lastframe.filename|escape }} in {{ lastframe.function|escape }}, line {{ lastframe.lineno }} |
Python Executable: | {{ sys_executable|escape }} |
Python Version: | {{ sys_version_info }} |
Python Path: | {{ sys_path }} |
Server time: | {{server_time|date:"r"}} |
The string that could not be encoded/decoded was: {{ unicode_hint|escape }}
Django tried loading these templates, in this order:
{{ loader.loader }}
:
{{ t.name }}
(File {% if t.exists %}exists{% else %}does not exist{% endif %})Django couldn't find any templates because your TEMPLATE_LOADERS
setting is empty!
In template {{ template_info.name }}
, error at line {{ template_info.line }}
{{ source_line.0 }} | {{ template_info.before }}{{ template_info.during }}{{ template_info.after }} |
---|---|
{{ source_line.0 }} | {{ source_line.1 }} |
{{ frame.filename|escape }}
in {{ frame.function|escape }}
{% if frame.context_line %}
Variable | Value |
---|---|
{{ var.0|escape }} | {{ var.1|pprint|escape }} |
Variable | Value |
---|---|
{{ var.0 }} | {{ var.1|pprint }} |
No GET data
{% endif %}Variable | Value |
---|---|
{{ var.0 }} | {{ var.1|pprint }} |
No POST data
{% endif %}Variable | Value |
---|---|
{{ var.0 }} | {{ var.1|pprint }} |
No FILES data
{% endif %}Variable | Value |
---|---|
{{ var.0 }} | {{ var.1|pprint }} |
No cookie data
{% endif %}Variable | Value |
---|---|
{{ var.0 }} | {{ var.1|pprint }} |
{{ settings.SETTINGS_MODULE }}
Setting | Value |
---|---|
{{ var.0 }} | {{ var.1|pprint }} |
You're seeing this error because you have DEBUG = True
in your
Django settings file. Change that to False
, and Django will
display a standard 500 page.
Request Method: | {{ request.META.REQUEST_METHOD }} |
---|---|
Request URL: | {{ request.build_absolute_uri|escape }} |
Using the URLconf defined in {{ settings.ROOT_URLCONF }}
,
Django tried these URL patterns, in this order:
The current URL, {{ request_path|escape }}
, didn't match any of these.
{{ reason }}
{% endif %}
You're seeing this error because you have DEBUG = True
in
your Django settings file. Change that to False
, and Django
will display a standard 404 page.
Of course, you haven't actually done any work yet. Here's what to do next:
DATABASE_*
settings in {{ project_name }}/settings.py
.python {{ project_name }}/manage.py startapp [appname]
.
You're seeing this message because you have DEBUG = True
in your
Django settings file and you haven't configured any URLs. Get to work!