from __future__ import unicode_literals import datetime import os import re import sys import types from django.conf import settings from django.core.exceptions import ImproperlyConfigured from django.core.urlresolvers import resolve, Resolver404 from django.http import (HttpResponse, HttpResponseNotFound, HttpRequest, build_request_repr) from django.template import Context, Engine, TemplateDoesNotExist from django.template.defaultfilters import force_escape, pprint from django.utils.datastructures import MultiValueDict from django.utils.html import escape from django.utils.encoding import force_bytes, smart_text from django.utils import lru_cache from django.utils.module_loading import import_string from django.utils import six from django.utils.translation import ugettext as _ # Minimal Django templates engine to render the error templates # regardless of the project's TEMPLATES setting. DEBUG_ENGINE = Engine(debug=True) HIDDEN_SETTINGS = re.compile('API|TOKEN|KEY|SECRET|PASS|SIGNATURE') CLEANSED_SUBSTITUTE = '********************' 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 class CallableSettingWrapper(object): """ Object to wrap callable appearing in settings * Not to call in the debug page (#21345). * Not to break the debug page if the callable forbidding to set attributes (#23070). """ def __init__(self, callable_setting): self._wrapped = callable_setting def __repr__(self): return repr(self._wrapped) def cleanse_setting(key, value): """Cleanse an individual setting key/value of sensitive content. If the value is a dictionary, recursively cleanse the keys in that dictionary. """ try: if HIDDEN_SETTINGS.search(key): cleansed = CLEANSED_SUBSTITUTE else: if isinstance(value, dict): cleansed = {k: cleanse_setting(k, v) for k, v in value.items()} else: cleansed = value except TypeError: # If the key isn't regex-able, just return as-is. cleansed = value if callable(cleansed): # For fixing #21345 and #23070 cleansed = CallableSettingWrapper(cleansed) return cleansed 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(): settings_dict[k] = cleanse_setting(k, getattr(settings, k)) return settings_dict def technical_500_response(request, exc_type, exc_value, tb, status_code=500): """ 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) if request.is_ajax(): text = reporter.get_traceback_text() return HttpResponse(text, status=status_code, content_type='text/plain') else: html = reporter.get_traceback_html() return HttpResponse(html, status=status_code, content_type='text/html') @lru_cache.lru_cache() def get_default_exception_reporter_filter(): # Instantiate the default filter for the first time and cache it. return import_string(settings.DEFAULT_EXCEPTION_REPORTER_FILTER)() def get_exception_reporter_filter(request): default_filter = get_default_exception_reporter_filter() return getattr(request, 'exception_reporter_filter', default_filter) class ExceptionReporterFilter(object): """ Base for all exception reporter filter classes. All overridable hooks contain lenient default behaviors. """ def get_request_repr(self, request): if request is None: return repr(None) else: return build_request_repr(request, POST_override=self.get_post_parameters(request)) def get_post_parameters(self, request): if request is None: return {} else: return request.POST def get_traceback_frame_variables(self, request, tb_frame): return list(six.iteritems(tb_frame.f_locals)) class SafeExceptionReporterFilter(ExceptionReporterFilter): """ Use annotations made by the sensitive_post_parameters and sensitive_variables decorators to filter out sensitive information. """ def is_active(self, request): """ This filter is to add safety in production environments (i.e. DEBUG is False). If DEBUG is True then your site is not safe anyway. This hook is provided as a convenience to easily activate or deactivate the filter on a per request basis. """ return settings.DEBUG is False def get_cleansed_multivaluedict(self, request, multivaluedict): """ Replaces the keys in a MultiValueDict marked as sensitive with stars. This mitigates leaking sensitive POST parameters if something like request.POST['nonexistent_key'] throws an exception (#21098). """ sensitive_post_parameters = getattr(request, 'sensitive_post_parameters', []) if self.is_active(request) and sensitive_post_parameters: multivaluedict = multivaluedict.copy() for param in sensitive_post_parameters: if param in multivaluedict: multivaluedict[param] = CLEANSED_SUBSTITUTE return multivaluedict def get_post_parameters(self, request): """ Replaces the values of POST parameters marked as sensitive with stars (*********). """ if request is None: return {} else: sensitive_post_parameters = getattr(request, 'sensitive_post_parameters', []) if self.is_active(request) and sensitive_post_parameters: cleansed = request.POST.copy() if sensitive_post_parameters == '__ALL__': # Cleanse all parameters. for k, v in cleansed.items(): cleansed[k] = CLEANSED_SUBSTITUTE return cleansed else: # Cleanse only the specified parameters. for param in sensitive_post_parameters: if param in cleansed: cleansed[param] = CLEANSED_SUBSTITUTE return cleansed else: return request.POST def cleanse_special_types(self, request, value): if isinstance(value, HttpRequest): # Cleanse the request's POST parameters. value = self.get_request_repr(value) elif isinstance(value, MultiValueDict): # Cleanse MultiValueDicts (request.POST is the one we usually care about) value = self.get_cleansed_multivaluedict(request, value) return value def get_traceback_frame_variables(self, request, tb_frame): """ Replaces the values of variables marked as sensitive with stars (*********). """ # Loop through the frame's callers to see if the sensitive_variables # decorator was used. current_frame = tb_frame.f_back sensitive_variables = None while current_frame is not None: if (current_frame.f_code.co_name == 'sensitive_variables_wrapper' and 'sensitive_variables_wrapper' in current_frame.f_locals): # The sensitive_variables decorator was used, so we take note # of the sensitive variables' names. wrapper = current_frame.f_locals['sensitive_variables_wrapper'] sensitive_variables = getattr(wrapper, 'sensitive_variables', None) break current_frame = current_frame.f_back cleansed = {} if self.is_active(request) and sensitive_variables: if sensitive_variables == '__ALL__': # Cleanse all variables for name, value in tb_frame.f_locals.items(): cleansed[name] = CLEANSED_SUBSTITUTE else: # Cleanse specified variables for name, value in tb_frame.f_locals.items(): if name in sensitive_variables: value = CLEANSED_SUBSTITUTE else: value = self.cleanse_special_types(request, value) cleansed[name] = value else: # Potentially cleanse the request and any MultiValueDicts if they # are one of the frame variables. for name, value in tb_frame.f_locals.items(): cleansed[name] = self.cleanse_special_types(request, value) if (tb_frame.f_code.co_name == 'sensitive_variables_wrapper' and 'sensitive_variables_wrapper' in tb_frame.f_locals): # For good measure, obfuscate the decorated function's arguments in # the sensitive_variables decorator's frame, in case the variables # associated with those arguments were meant to be obfuscated from # the decorated function's frame. cleansed['func_args'] = CLEANSED_SUBSTITUTE cleansed['func_kwargs'] = CLEANSED_SUBSTITUTE return cleansed.items() class ExceptionReporter(object): """ A class to organize and coordinate reporting on exceptions. """ def __init__(self, request, exc_type, exc_value, tb, is_email=False): self.request = request self.filter = get_exception_reporter_filter(self.request) self.exc_type = exc_type self.exc_value = exc_value self.tb = tb self.is_email = is_email self.template_info = None self.template_does_not_exist = False self.loader_debug_info = None # Handle deprecated string exceptions if isinstance(self.exc_type, six.string_types): self.exc_value = Exception('Deprecated String Exception: %r' % self.exc_type) self.exc_type = type(self.exc_value) def format_path_status(self, path): if not os.path.exists(path): return "File does not exist" if not os.path.isfile(path): return "Not a file" if not os.access(path, os.R_OK): return "File is not readable" return "File exists" def get_traceback_data(self): """Return a dictionary containing traceback information.""" try: default_template_engine = Engine.get_default() except ImproperlyConfigured: default_template_engine = None # TODO: add support for multiple template engines (#24120). # TemplateDoesNotExist should carry all the information. # Replaying the search process isn't a good design. if self.exc_type and issubclass(self.exc_type, TemplateDoesNotExist): if default_template_engine is None: template_loaders = [] else: self.template_does_not_exist = True self.loader_debug_info = [] # If Django fails in get_template_loaders, provide an empty list # for the following loop to not fail. try: template_loaders = default_template_engine.template_loaders except Exception: template_loaders = [] for loader in template_loaders: try: source_list_func = loader.get_template_sources # NOTE: This assumes exc_value is the name of the template that # the loader attempted to load. template_list = [{ 'name': t, 'status': self.format_path_status(t), } for t in source_list_func(str(self.exc_value))] except AttributeError: template_list = [] loader_name = loader.__module__ + '.' + loader.__class__.__name__ self.loader_debug_info.append({ 'loader': loader_name, 'templates': template_list, }) # TODO: add support for multiple template engines (#24119). if (default_template_engine is not None and default_template_engine.debug and hasattr(self.exc_value, 'django_template_source')): self.get_template_exception_info() frames = self.get_traceback_frames() for i, frame in enumerate(frames): if 'vars' in frame: frame_vars = [] for k, v in frame['vars']: v = pprint(v) # The force_escape filter assume unicode, make sure that works if isinstance(v, six.binary_type): v = v.decode('utf-8', 'replace') # don't choke on non-utf-8 input # Trim large blobs of data if len(v) > 4096: v = '%s... ' % (v[0:4096], len(v)) frame_vars.append((k, force_escape(v))) frame['vars'] = frame_vars frames[i] = frame unicode_hint = '' if self.exc_type and 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_text( unicode_str[max(start - 5, 0):min(end + 5, len(unicode_str))], 'ascii', errors='replace' ) from django import get_version c = { 'is_email': self.is_email, 'unicode_hint': unicode_hint, 'frames': frames, 'request': self.request, 'filtered_POST': self.filter.get_post_parameters(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, } # Check whether exception info is available if self.exc_type: c['exception_type'] = self.exc_type.__name__ if self.exc_value: c['exception_value'] = smart_text(self.exc_value, errors='replace') if frames: c['lastframe'] = frames[-1] return c def get_traceback_html(self): "Return HTML version of debug 500 HTTP error page." t = DEBUG_ENGINE.from_string(TECHNICAL_500_TEMPLATE) c = Context(self.get_traceback_data(), use_l10n=False) return t.render(c) def get_traceback_text(self): "Return plain text version of debug 500 HTTP error page." t = DEBUG_ENGINE.from_string(TECHNICAL_500_TEXT_TEMPLATE) c = Context(self.get_traceback_data(), autoescape=False, use_l10n=False) return t.render(c) def get_template_exception_info(self): origin, (start, end) = self.exc_value.django_template_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) # In some rare cases, exc_value.args might be empty. try: message = self.exc_value.args[0] except IndexError: message = '(Could not get exception message)' self.template_info = { 'message': message, '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"): try: source = loader.get_source(module_name) except ImportError: pass if source is not None: source = source.splitlines() if source is None: try: with open(filename, 'rb') as fp: source = fp.read().splitlines() except (OSError, IOError): pass if source is None: return None, [], None, [] # If we just read the source from a file, or if the loader did not # apply tokenize.detect_encoding to decode the source into a Unicode # string, then we should do that ourselves. if isinstance(source[0], six.binary_type): 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(br'coding[:=]\s*([-\w.]+)', line) if match: encoding = match.group(1).decode('ascii') break source = [six.text_type(sline, encoding, 'replace') for sline in source] lower_bound = max(0, lineno - context_lines) upper_bound = lineno + context_lines pre_context = source[lower_bound:lineno] context_line = source[lineno] post_context = 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__') or '' 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, 'type': 'django' if module_name.startswith('django.') else 'user', 'filename': filename, 'function': function, 'lineno': lineno + 1, 'vars': self.filter.get_traceback_frame_variables(self.request, tb.tb_frame), '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 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: error_url = exception.args[0]['path'] except (IndexError, TypeError, KeyError): error_url = request.path_info[1:] # Trim leading slash try: tried = exception.args[0]['tried'] except (IndexError, TypeError, KeyError): tried = [] else: if (not tried # empty URLconf or (request.path == '/' and len(tried) == 1 # default URLconf and len(tried[0]) == 1 and getattr(tried[0][0], 'app_name', '') == getattr(tried[0][0], 'namespace', '') == 'admin')): return default_urlconf(request) urlconf = getattr(request, 'urlconf', settings.ROOT_URLCONF) if isinstance(urlconf, types.ModuleType): urlconf = urlconf.__name__ caller = '' try: resolver_match = resolve(request.path) except Resolver404: pass else: obj = resolver_match.func if hasattr(obj, '__name__'): caller = obj.__name__ elif hasattr(obj, '__class__') and hasattr(obj.__class__, '__name__'): caller = obj.__class__.__name__ if hasattr(obj, '__module__'): module = obj.__module__ caller = '%s.%s' % (module, caller) t = DEBUG_ENGINE.from_string(TECHNICAL_404_TEMPLATE) c = Context({ 'urlconf': urlconf, 'root_urlconf': settings.ROOT_URLCONF, 'request_path': error_url, 'urlpatterns': tried, 'reason': force_bytes(exception, errors='replace'), 'request': request, 'settings': get_safe_settings(), 'raising_view_name': caller, }) return HttpResponseNotFound(t.render(c), content_type='text/html') def default_urlconf(request): "Create an empty URLconf 404 error response." t = DEBUG_ENGINE.from_string(DEFAULT_URLCONF_TEMPLATE) c = Context({ "title": _("Welcome to Django"), "heading": _("It worked!"), "subheading": _("Congratulations on your first Django-powered page."), "instructions": _("Of course, you haven't actually done any work yet. " "Next, start your first app by running python manage.py startapp [app_label]."), "explanation": _("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!"), }) return HttpResponse(t.render(c), content_type='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 = (""" {% if exception_type %}{{ exception_type }}{% else %}Report{% endif %}""" """{% if request %} at {{ request.path_info|escape }}{% endif %} {% if not is_email %} {% endif %}

{% if exception_type %}{{ exception_type }}{% else %}Report{% endif %}""" """{% if request %} at {{ request.path_info|escape }}{% endif %}

"""
 """{% if exception_value %}{{ exception_value|force_escape }}{% else %}No exception message supplied{% endif %}"""
"""
{% if request %} {% endif %} {% if exception_type %} {% endif %} {% if exception_type and exception_value %} {% endif %} {% if lastframe %} {% endif %}
Request Method: {{ request.META.REQUEST_METHOD }}
Request URL: {{ request.build_absolute_uri|escape }}
Django Version: {{ django_version_info }}
Exception Type: {{ exception_type }}
Exception Value:
{{ exception_value|force_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|pprint }}
Server time: {{server_time|date:"r"}}
{% if unicode_hint %}

Unicode error hint

The string that could not be encoded/decoded was: {{ unicode_hint|force_escape }}

{% endif %} {% if template_does_not_exist %}

Template-loader postmortem

{% if loader_debug_info %}

Django tried loading these templates, in this order:

{% else %}

Django couldn't find any templates because your 'loaders' option is empty!

{% endif %}
{% endif %} {% if template_info %}

Error during template rendering

In template {{ template_info.name }}, error at line {{ template_info.line }}

{{ template_info.message }}

{% for source_line in template_info.source_lines %} {% ifequal source_line.0 template_info.line %} {% else %} {% endifequal %} {% endfor %}
{{ source_line.0 }} {{ template_info.before }} {{ template_info.during }} {{ template_info.after }}
{{ source_line.0 }} {{ source_line.1 }}
{% endif %} {% if frames %}

Traceback {% if not is_email %} Switch to copy-and-paste view{% endif %}

{% autoescape off %}
    {% for frame in frames %}
  • {{ frame.filename|escape }} in {{ frame.function|escape }} {% if frame.context_line %}
    {% if frame.pre_context and not is_email %}
      {% for line in frame.pre_context %}
    1. {{ line|escape }}
    2. {% endfor %}
    {% endif %}
    1.             {{ frame.context_line|escape }}
      {% if not is_email %} ...{% endif %}
    {% if frame.post_context and not is_email %}
      {% for line in frame.post_context %}
    1. {{ line|escape }}
    2. {% endfor %}
    {% endif %}
    {% endif %} {% if frame.vars %}
    {% if is_email %}

    Local Vars

    {% else %} Local vars {% endif %}
    {% for var in frame.vars|dictsort:"0" %} {% endfor %}
    Variable Value
    {{ var.0|force_escape }}
    {{ var.1 }}
    {% endif %}
  • {% endfor %}
{% endautoescape %}
{% if not is_email %}


{% endif %} {% endif %}

Request information

{% if request %}

GET

{% if request.GET %} {% for var in request.GET.items %} {% endfor %}
Variable Value
{{ var.0 }}
{{ var.1|pprint }}
{% else %}

No GET data

{% endif %}

POST

{% if filtered_POST %} {% for var in filtered_POST.items %} {% endfor %}
Variable Value
{{ var.0 }}
{{ var.1|pprint }}
{% else %}

No POST data

{% endif %}

FILES

{% if request.FILES %} {% for var in request.FILES.items %} {% endfor %}
Variable Value
{{ var.0 }}
{{ var.1|pprint }}
{% else %}

No FILES data

{% endif %} {% if request.COOKIES %} {% for var in request.COOKIES.items %} {% endfor %}
Variable Value
{{ var.0 }}
{{ var.1|pprint }}
{% else %}

No cookie data

{% endif %}

META

{% for var in request.META.items|dictsort:"0" %} {% endfor %}
Variable Value
{{ var.0 }}
{{ var.1|pprint }}
{% else %}

Request data not supplied

{% endif %}

Settings

Using settings module {{ settings.SETTINGS_MODULE }}

{% for var in settings.items|dictsort:"0" %} {% endfor %}
Setting Value
{{ var.0 }}
{{ var.1|pprint }}
{% if not is_email %}

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 page generated by the handler for this status code.

{% endif %} """) TECHNICAL_500_TEXT_TEMPLATE = """{% firstof exception_type 'Report' %}{% if request %} at {{ request.path_info }}{% endif %} {% firstof exception_value 'No exception message supplied' %} {% if request %} Request Method: {{ request.META.REQUEST_METHOD }} Request URL: {{ request.build_absolute_uri }}{% endif %} Django Version: {{ django_version_info }} Python Executable: {{ sys_executable }} Python Version: {{ sys_version_info }} Python Path: {{ sys_path }} Server time: {{server_time|date:"r"}} Installed Applications: {{ settings.INSTALLED_APPS|pprint }} Installed Middleware: {{ settings.MIDDLEWARE_CLASSES|pprint }} {% if template_does_not_exist %}Template loader Error: {% if loader_debug_info %}Django tried loading these templates, in this order: {% for loader in loader_debug_info %}Using loader {{ loader.loader }}: {% for t in loader.templates %}{{ t.name }} ({{ t.status }}) {% endfor %}{% endfor %} {% else %}Django couldn't find any templates because your 'loaders' option is empty! {% endif %} {% endif %}{% if template_info %} Template error: In template {{ template_info.name }}, error at line {{ template_info.line }} {{ template_info.message }}{% for source_line in template_info.source_lines %} {% ifequal source_line.0 template_info.line %} {{ source_line.0 }} : {{ template_info.before }} {{ template_info.during }} {{ template_info.after }} {% else %} {{ source_line.0 }} : {{ source_line.1 }} {% endifequal %}{% endfor %}{% endif %}{% if frames %} Traceback: {% for frame in frames %}File "{{ frame.filename }}" in {{ frame.function }} {% if frame.context_line %} {{ frame.lineno }}. {{ frame.context_line }}{% endif %} {% endfor %} {% if exception_type %}Exception Type: {{ exception_type }}{% if request %} at {{ request.path_info }}{% endif %} {% if exception_value %}Exception Value: {{ exception_value }}{% endif %}{% endif %}{% endif %} {% if request %}Request information: GET:{% for k, v in request.GET.items %} {{ k }} = {{ v|stringformat:"r" }}{% empty %} No GET data{% endfor %} POST:{% for k, v in filtered_POST.items %} {{ k }} = {{ v|stringformat:"r" }}{% empty %} No POST data{% endfor %} FILES:{% for k, v in request.FILES.items %} {{ k }} = {{ v|stringformat:"r" }}{% empty %} No FILES data{% endfor %} COOKIES:{% for k, v in request.COOKIES.items %} {{ k }} = {{ v|stringformat:"r" }}{% empty %} No cookie data{% endfor %} META:{% for k, v in request.META.items|dictsort:"0" %} {{ k }} = {{ v|stringformat:"r" }}{% endfor %} {% else %}Request data not supplied {% endif %} Settings: Using settings module {{ settings.SETTINGS_MODULE }}{% for k, v in settings.items|dictsort:"0" %} {{ k }} = {{ v|stringformat:"r" }}{% endfor %} 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 page generated by the handler for this status code. """ TECHNICAL_404_TEMPLATE = """ Page not found at {{ request.path_info|escape }}

Page not found (404)

{% if raising_view_name %} {% endif %}
Request Method: {{ request.META.REQUEST_METHOD }}
Request URL: {{ request.build_absolute_uri|escape }}
Raised by: {{ raising_view_name }}
{% if urlpatterns %}

Using the URLconf defined in {{ urlconf }}, Django tried these URL patterns, in this order:

    {% for pattern in urlpatterns %}
  1. {% for pat in pattern %} {{ pat.regex.pattern }} {% if forloop.last and pat.name %}[name='{{ pat.name }}']{% endif %} {% endfor %}
  2. {% endfor %}

The current URL, {{ request_path|escape }}, didn't match any of these.

{% else %}

{{ 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.

""" DEFAULT_URLCONF_TEMPLATE = """ {{ title }}

{{ heading }}

{{ subheading }}

{{ instructions|safe }}

{{ explanation|safe }}

"""