summaryrefslogtreecommitdiff
path: root/lib/python2.7/site-packages/django/views
diff options
context:
space:
mode:
authorttt2017-05-13 00:29:47 +0530
committerttt2017-05-13 00:29:47 +0530
commitabf599be33b383a6a5baf9493093b2126a622ac8 (patch)
tree4c5ab6e0d935d5e65fabcf0258e4a00dd20a5afa /lib/python2.7/site-packages/django/views
downloadSBHS-2018-Rpi-abf599be33b383a6a5baf9493093b2126a622ac8.tar.gz
SBHS-2018-Rpi-abf599be33b383a6a5baf9493093b2126a622ac8.tar.bz2
SBHS-2018-Rpi-abf599be33b383a6a5baf9493093b2126a622ac8.zip
added all server files
Diffstat (limited to 'lib/python2.7/site-packages/django/views')
-rw-r--r--lib/python2.7/site-packages/django/views/__init__.py0
-rw-r--r--lib/python2.7/site-packages/django/views/csrf.py104
-rw-r--r--lib/python2.7/site-packages/django/views/debug.py1150
-rw-r--r--lib/python2.7/site-packages/django/views/decorators/__init__.py0
-rw-r--r--lib/python2.7/site-packages/django/views/decorators/cache.py55
-rw-r--r--lib/python2.7/site-packages/django/views/decorators/clickjacking.py64
-rw-r--r--lib/python2.7/site-packages/django/views/decorators/csrf.py59
-rw-r--r--lib/python2.7/site-packages/django/views/decorators/debug.py77
-rw-r--r--lib/python2.7/site-packages/django/views/decorators/gzip.py5
-rw-r--r--lib/python2.7/site-packages/django/views/decorators/http.py166
-rw-r--r--lib/python2.7/site-packages/django/views/decorators/vary.py39
-rw-r--r--lib/python2.7/site-packages/django/views/defaults.py91
-rw-r--r--lib/python2.7/site-packages/django/views/generic/__init__.py12
-rw-r--r--lib/python2.7/site-packages/django/views/generic/base.py219
-rw-r--r--lib/python2.7/site-packages/django/views/generic/dates.py785
-rw-r--r--lib/python2.7/site-packages/django/views/generic/detail.py173
-rw-r--r--lib/python2.7/site-packages/django/views/generic/edit.py280
-rw-r--r--lib/python2.7/site-packages/django/views/generic/list.py189
-rw-r--r--lib/python2.7/site-packages/django/views/i18n.py305
-rw-r--r--lib/python2.7/site-packages/django/views/static.py143
20 files changed, 3916 insertions, 0 deletions
diff --git a/lib/python2.7/site-packages/django/views/__init__.py b/lib/python2.7/site-packages/django/views/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/__init__.py
diff --git a/lib/python2.7/site-packages/django/views/csrf.py b/lib/python2.7/site-packages/django/views/csrf.py
new file mode 100644
index 0000000..c95d19d
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/csrf.py
@@ -0,0 +1,104 @@
+from django.http import HttpResponseForbidden
+from django.template import Context, Template
+from django.conf import settings
+
+# We include the template inline since we need to be able to reliably display
+# this error message, especially for the sake of developers, and there isn't any
+# other way of making it available independent of what is in the settings file.
+
+CSRF_FAILURE_TEMPLATE = """
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <meta name="robots" content="NONE,NOARCHIVE">
+ <title>403 Forbidden</title>
+ <style type="text/css">
+ html * { padding:0; margin:0; }
+ body * { padding:10px 20px; }
+ body * * { padding:0; }
+ body { font:small sans-serif; background:#eee; }
+ body>div { border-bottom:1px solid #ddd; }
+ h1 { font-weight:normal; margin-bottom:.4em; }
+ h1 span { font-size:60%; color:#666; font-weight:normal; }
+ #info { background:#f6f6f6; }
+ #info ul { margin: 0.5em 4em; }
+ #info p, #summary p { padding-top:10px; }
+ #summary { background: #ffc; }
+ #explanation { background:#eee; border-bottom: 0px none; }
+ </style>
+</head>
+<body>
+<div id="summary">
+ <h1>Forbidden <span>(403)</span></h1>
+ <p>CSRF verification failed. Request aborted.</p>
+{% if no_referer %}
+ <p>You are seeing this message because this HTTPS site requires a 'Referer
+ header' to be sent by your Web browser, but none was sent. This header is
+ required for security reasons, to ensure that your browser is not being
+ hijacked by third parties.</p>
+
+ <p>If you have configured your browser to disable 'Referer' headers, please
+ re-enable them, at least for this site, or for HTTPS connections, or for
+ 'same-origin' requests.</p>
+{% endif %}
+</div>
+{% if DEBUG %}
+<div id="info">
+ <h2>Help</h2>
+ {% if reason %}
+ <p>Reason given for failure:</p>
+ <pre>
+ {{ reason }}
+ </pre>
+ {% endif %}
+
+ <p>In general, this can occur when there is a genuine Cross Site Request Forgery, or when
+ <a
+ href='http://docs.djangoproject.com/en/dev/ref/contrib/csrf/#ref-contrib-csrf'>Django's
+ CSRF mechanism</a> has not been used correctly. For POST forms, you need to
+ ensure:</p>
+
+ <ul>
+ <li>Your browser is accepting cookies.</li>
+
+ <li>The view function uses <a
+ href='http://docs.djangoproject.com/en/dev/ref/templates/api/#subclassing-context-requestcontext'><code>RequestContext</code></a>
+ for the template, instead of <code>Context</code>.</li>
+
+ <li>In the template, there is a <code>{% templatetag openblock %} csrf_token
+ {% templatetag closeblock %}</code> template tag inside each POST form that
+ targets an internal URL.</li>
+
+ <li>If you are not using <code>CsrfViewMiddleware</code>, then you must use
+ <code>csrf_protect</code> on any views that use the <code>csrf_token</code>
+ template tag, as well as those that accept the POST data.</li>
+
+ </ul>
+
+ <p>You're seeing the help section of this page because you have <code>DEBUG =
+ True</code> in your Django settings file. Change that to <code>False</code>,
+ and only the initial error message will be displayed. </p>
+
+ <p>You can customize this page using the CSRF_FAILURE_VIEW setting.</p>
+</div>
+{% else %}
+<div id="explanation">
+ <p><small>More information is available with DEBUG=True.</small></p>
+</div>
+{% endif %}
+</body>
+</html>
+"""
+
+def csrf_failure(request, reason=""):
+ """
+ Default view used when request fails CSRF protection
+ """
+ from django.middleware.csrf import REASON_NO_REFERER
+ t = Template(CSRF_FAILURE_TEMPLATE)
+ c = Context({'DEBUG': settings.DEBUG,
+ 'reason': reason,
+ 'no_referer': reason == REASON_NO_REFERER
+ })
+ return HttpResponseForbidden(t.render(c), content_type='text/html')
diff --git a/lib/python2.7/site-packages/django/views/debug.py b/lib/python2.7/site-packages/django/views/debug.py
new file mode 100644
index 0000000..a610c55
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/debug.py
@@ -0,0 +1,1150 @@
+from __future__ import unicode_literals
+
+import datetime
+import os
+import re
+import sys
+import types
+
+from django.conf import settings
+from django.http import (HttpResponse, HttpResponseServerError,
+ HttpResponseNotFound, HttpRequest, build_request_repr)
+from django.template import Template, Context, 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.module_loading import import_by_path
+from django.utils import six
+
+HIDDEN_SETTINGS = re.compile('API|TOKEN|KEY|SECRET|PASS|PROFANITIES_LIST|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
+
+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 = dict((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
+ 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):
+ """
+ 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 HttpResponseServerError(text, content_type='text/plain')
+ else:
+ html = reporter.get_traceback_html()
+ return HttpResponseServerError(html, content_type='text/html')
+
+# Cache for the default exception reporter filter instance.
+default_exception_reporter_filter = None
+
+def get_exception_reporter_filter(request):
+ global default_exception_reporter_filter
+ if default_exception_reporter_filter is None:
+ # Load the default filter for the first time and cache it.
+ default_exception_reporter_filter = import_by_path(
+ settings.DEFAULT_EXCEPTION_REPORTER_FILTER)()
+ if request:
+ return getattr(request, 'exception_reporter_filter', default_exception_reporter_filter)
+ else:
+ return default_exception_reporter_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 Context instance containing traceback information."
+
+ if self.exc_type and issubclass(self.exc_type, TemplateDoesNotExist):
+ from django.template.loader import template_source_loaders
+ self.template_does_not_exist = True
+ self.loader_debug_info = []
+ # If the template_source_loaders haven't been populated yet, you need
+ # to provide an empty list for this for loop to not fail.
+ if template_source_loaders is None:
+ template_source_loaders = []
+ for loader in template_source_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,
+ })
+ if (settings.TEMPLATE_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'] = [(k, force_escape(pprint(v))) for k, v in 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 = Template(TECHNICAL_500_TEMPLATE, name='Technical 500 template')
+ c = Context(self.get_traceback_data())
+ return t.render(c)
+
+ def get_traceback_text(self):
+ "Return plain text version of debug 500 HTTP error page."
+ t = Template(TECHNICAL_500_TEXT_TEMPLATE, name='Technical 500 template')
+ c = Context(self.get_traceback_data(), autoescape=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:
+ 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__
+
+ t = Template(TECHNICAL_404_TEMPLATE, name='Technical 404 template')
+ c = Context({
+ 'urlconf': urlconf,
+ 'root_urlconf': settings.ROOT_URLCONF,
+ 'request_path': request.path_info[1:], # Trim leading slash
+ 'urlpatterns': tried,
+ 'reason': force_bytes(exception, errors='replace'),
+ 'request': request,
+ 'settings': get_safe_settings(),
+ })
+ return HttpResponseNotFound(t.render(c), content_type='text/html')
+
+def default_urlconf(request):
+ "Create an empty URLconf 404 error response."
+ t = Template(DEFAULT_URLCONF_TEMPLATE, name='Default URLconf template')
+ c = Context({})
+ 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 = """
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <meta name="robots" content="NONE,NOARCHIVE">
+ <title>{% if exception_type %}{{ exception_type }}{% else %}Report{% endif %}{% if request %} at {{ request.path_info|escape }}{% endif %}</title>
+ <style type="text/css">
+ html * { padding:0; margin:0; }
+ body * { padding:10px 20px; }
+ body * * { padding:0; }
+ body { font:small sans-serif; }
+ body>div { border-bottom:1px solid #ddd; }
+ h1 { font-weight:normal; }
+ h2 { margin-bottom:.8em; }
+ h2 span { font-size:80%; color:#666; font-weight:normal; }
+ h3 { margin:1em 0 .5em 0; }
+ h4 { margin:0 0 .5em 0; font-weight: normal; }
+ code, pre { font-size: 100%; white-space: pre-wrap; }
+ table { border:1px solid #ccc; border-collapse: collapse; width:100%; background:white; }
+ tbody td, tbody th { vertical-align:top; padding:2px 3px; }
+ thead th { padding:1px 6px 1px 3px; background:#fefefe; text-align:left; font-weight:normal; font-size:11px; border:1px solid #ddd; }
+ tbody th { width:12em; text-align:right; color:#666; padding-right:.5em; }
+ table.vars { margin:5px 0 2px 40px; }
+ table.vars td, table.req td { font-family:monospace; }
+ table td.code { width:100%; }
+ table td.code pre { overflow:hidden; }
+ table.source th { color:#666; }
+ table.source td { font-family:monospace; white-space:pre; border-bottom:1px solid #eee; }
+ ul.traceback { list-style-type:none; color: #222; }
+ ul.traceback li.frame { padding-bottom:1em; color:#666; }
+ ul.traceback li.user { background-color:#e0e0e0; color:#000 }
+ div.context { padding:10px 0; overflow:hidden; }
+ div.context ol { padding-left:30px; margin:0 10px; list-style-position: inside; }
+ div.context ol li { font-family:monospace; white-space:pre; color:#777; cursor:pointer; }
+ div.context ol li pre { display:inline; }
+ div.context ol.context-line li { color:#505050; background-color:#dfdfdf; }
+ div.context ol.context-line li span { position:absolute; right:32px; }
+ .user div.context ol.context-line li { background-color:#bbb; color:#000; }
+ .user div.context ol li { color:#666; }
+ div.commands { margin-left: 40px; }
+ div.commands a { color:#555; text-decoration:none; }
+ .user div.commands a { color: black; }
+ #summary { background: #ffc; }
+ #summary h2 { font-weight: normal; color: #666; }
+ #explanation { background:#eee; }
+ #template, #template-not-exist { background:#f6f6f6; }
+ #template-not-exist ul { margin: 0 0 0 20px; }
+ #unicode-hint { background:#eee; }
+ #traceback { background:#eee; }
+ #requestinfo { background:#f6f6f6; padding-left:120px; }
+ #summary table { border:none; background:transparent; }
+ #requestinfo h2, #requestinfo h3 { position:relative; margin-left:-100px; }
+ #requestinfo h3 { margin-bottom:-1em; }
+ .error { background: #ffc; }
+ .specific { color:#cc3300; font-weight:bold; }
+ h2 span.commands { font-size:.7em;}
+ span.commands a:link {color:#5E5694;}
+ pre.exception_value { font-family: sans-serif; color: #666; font-size: 1.5em; margin: 10px 0 10px 0; }
+ </style>
+ {% if not is_email %}
+ <script type="text/javascript">
+ //<!--
+ function getElementsByClassName(oElm, strTagName, strClassName){
+ // Written by Jonathan Snook, http://www.snook.ca/jon; Add-ons by Robert Nyman, http://www.robertnyman.com
+ var arrElements = (strTagName == "*" && document.all)? document.all :
+ oElm.getElementsByTagName(strTagName);
+ var arrReturnElements = new Array();
+ strClassName = strClassName.replace(/\-/g, "\\-");
+ var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
+ var oElement;
+ for(var i=0; i<arrElements.length; i++){
+ oElement = arrElements[i];
+ if(oRegExp.test(oElement.className)){
+ arrReturnElements.push(oElement);
+ }
+ }
+ return (arrReturnElements)
+ }
+ function hideAll(elems) {
+ for (var e = 0; e < elems.length; e++) {
+ elems[e].style.display = 'none';
+ }
+ }
+ window.onload = function() {
+ hideAll(getElementsByClassName(document, 'table', 'vars'));
+ hideAll(getElementsByClassName(document, 'ol', 'pre-context'));
+ hideAll(getElementsByClassName(document, 'ol', 'post-context'));
+ hideAll(getElementsByClassName(document, 'div', 'pastebin'));
+ }
+ function toggle() {
+ for (var i = 0; i < arguments.length; i++) {
+ var e = document.getElementById(arguments[i]);
+ if (e) {
+ e.style.display = e.style.display == 'none' ? 'block' : 'none';
+ }
+ }
+ return false;
+ }
+ function varToggle(link, id) {
+ toggle('v' + id);
+ var s = link.getElementsByTagName('span')[0];
+ var uarr = String.fromCharCode(0x25b6);
+ var darr = String.fromCharCode(0x25bc);
+ s.innerHTML = s.innerHTML == uarr ? darr : uarr;
+ return false;
+ }
+ function switchPastebinFriendly(link) {
+ s1 = "Switch to copy-and-paste view";
+ s2 = "Switch back to interactive view";
+ link.innerHTML = link.innerHTML == s1 ? s2 : s1;
+ toggle('browserTraceback', 'pastebinTraceback');
+ return false;
+ }
+ //-->
+ </script>
+ {% endif %}
+</head>
+<body>
+<div id="summary">
+ <h1>{% if exception_type %}{{ exception_type }}{% else %}Report{% endif %}{% if request %} at {{ request.path_info|escape }}{% endif %}</h1>
+ <pre class="exception_value">{% if exception_value %}{{ exception_value|force_escape }}{% else %}No exception message supplied{% endif %}</pre>
+ <table class="meta">
+{% if request %}
+ <tr>
+ <th>Request Method:</th>
+ <td>{{ request.META.REQUEST_METHOD }}</td>
+ </tr>
+ <tr>
+ <th>Request URL:</th>
+ <td>{{ request.build_absolute_uri|escape }}</td>
+ </tr>
+{% endif %}
+ <tr>
+ <th>Django Version:</th>
+ <td>{{ django_version_info }}</td>
+ </tr>
+{% if exception_type %}
+ <tr>
+ <th>Exception Type:</th>
+ <td>{{ exception_type }}</td>
+ </tr>
+{% endif %}
+{% if exception_type and exception_value %}
+ <tr>
+ <th>Exception Value:</th>
+ <td><pre>{{ exception_value|force_escape }}</pre></td>
+ </tr>
+{% endif %}
+{% if lastframe %}
+ <tr>
+ <th>Exception Location:</th>
+ <td>{{ lastframe.filename|escape }} in {{ lastframe.function|escape }}, line {{ lastframe.lineno }}</td>
+ </tr>
+{% endif %}
+ <tr>
+ <th>Python Executable:</th>
+ <td>{{ sys_executable|escape }}</td>
+ </tr>
+ <tr>
+ <th>Python Version:</th>
+ <td>{{ sys_version_info }}</td>
+ </tr>
+ <tr>
+ <th>Python Path:</th>
+ <td><pre>{{ sys_path|pprint }}</pre></td>
+ </tr>
+ <tr>
+ <th>Server time:</th>
+ <td>{{server_time|date:"r"}}</td>
+ </tr>
+ </table>
+</div>
+{% if unicode_hint %}
+<div id="unicode-hint">
+ <h2>Unicode error hint</h2>
+ <p>The string that could not be encoded/decoded was: <strong>{{ unicode_hint|force_escape }}</strong></p>
+</div>
+{% endif %}
+{% if template_does_not_exist %}
+<div id="template-not-exist">
+ <h2>Template-loader postmortem</h2>
+ {% if loader_debug_info %}
+ <p>Django tried loading these templates, in this order:</p>
+ <ul>
+ {% for loader in loader_debug_info %}
+ <li>Using loader <code>{{ loader.loader }}</code>:
+ <ul>
+ {% for t in loader.templates %}<li><code>{{ t.name }}</code> ({{ t.status }})</li>{% endfor %}
+ </ul>
+ </li>
+ {% endfor %}
+ </ul>
+ {% else %}
+ <p>Django couldn't find any templates because your <code>TEMPLATE_LOADERS</code> setting is empty!</p>
+ {% endif %}
+</div>
+{% endif %}
+{% if template_info %}
+<div id="template">
+ <h2>Error during template rendering</h2>
+ <p>In template <code>{{ template_info.name }}</code>, error at line <strong>{{ template_info.line }}</strong></p>
+ <h3>{{ template_info.message }}</h3>
+ <table class="source{% if template_info.top %} cut-top{% endif %}{% ifnotequal template_info.bottom template_info.total %} cut-bottom{% endifnotequal %}">
+ {% for source_line in template_info.source_lines %}
+ {% ifequal source_line.0 template_info.line %}
+ <tr class="error"><th>{{ source_line.0 }}</th>
+ <td>{{ template_info.before }}<span class="specific">{{ template_info.during }}</span>{{ template_info.after }}</td></tr>
+ {% else %}
+ <tr><th>{{ source_line.0 }}</th>
+ <td>{{ source_line.1 }}</td></tr>
+ {% endifequal %}
+ {% endfor %}
+ </table>
+</div>
+{% endif %}
+{% if frames %}
+<div id="traceback">
+ <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>
+ {% autoescape off %}
+ <div id="browserTraceback">
+ <ul class="traceback">
+ {% for frame in frames %}
+ <li class="frame {{ frame.type }}">
+ <code>{{ frame.filename|escape }}</code> in <code>{{ frame.function|escape }}</code>
+
+ {% if frame.context_line %}
+ <div class="context" id="c{{ frame.id }}">
+ {% if frame.pre_context and not is_email %}
+ <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>
+ {% endif %}
+ <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>
+ {% if frame.post_context and not is_email %}
+ <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>
+ {% endif %}
+ </div>
+ {% endif %}
+
+ {% if frame.vars %}
+ <div class="commands">
+ {% if is_email %}
+ <h2>Local Vars</h2>
+ {% else %}
+ <a href="#" onclick="return varToggle(this, '{{ frame.id }}')"><span>&#x25b6;</span> Local vars</a>
+ {% endif %}
+ </div>
+ <table class="vars" id="v{{ frame.id }}">
+ <thead>
+ <tr>
+ <th>Variable</th>
+ <th>Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for var in frame.vars|dictsort:"0" %}
+ <tr>
+ <td>{{ var.0|force_escape }}</td>
+ <td class="code"><pre>{{ var.1 }}</pre></td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% endif %}
+ </li>
+ {% endfor %}
+ </ul>
+ </div>
+ {% endautoescape %}
+ <form action="http://dpaste.com/" name="pasteform" id="pasteform" method="post">
+{% if not is_email %}
+ <div id="pastebinTraceback" class="pastebin">
+ <input type="hidden" name="language" value="PythonConsole">
+ <input type="hidden" name="title" value="{{ exception_type|escape }}{% if request %} at {{ request.path_info|escape }}{% endif %}">
+ <input type="hidden" name="source" value="Django Dpaste Agent">
+ <input type="hidden" name="poster" value="Django">
+ <textarea name="content" id="traceback_area" cols="140" rows="25">
+Environment:
+
+{% if request %}
+Request Method: {{ request.META.REQUEST_METHOD }}
+Request URL: {{ request.build_absolute_uri|escape }}
+{% endif %}
+Django Version: {{ django_version_info }}
+Python Version: {{ sys_version_info }}
+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 TEMPLATE_LOADERS setting 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 %}
+Traceback:
+{% for frame in frames %}File "{{ frame.filename|escape }}" in {{ frame.function|escape }}
+{% if frame.context_line %} {{ frame.lineno }}. {{ frame.context_line|escape }}{% endif %}
+{% endfor %}
+Exception Type: {{ exception_type|escape }}{% if request %} at {{ request.path_info|escape }}{% endif %}
+Exception Value: {{ exception_value|force_escape }}
+</textarea>
+ <br><br>
+ <input type="submit" value="Share this traceback on a public Web site">
+ </div>
+</form>
+</div>
+{% endif %}
+{% endif %}
+
+<div id="requestinfo">
+ <h2>Request information</h2>
+
+{% if request %}
+ <h3 id="get-info">GET</h3>
+ {% if request.GET %}
+ <table class="req">
+ <thead>
+ <tr>
+ <th>Variable</th>
+ <th>Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for var in request.GET.items %}
+ <tr>
+ <td>{{ var.0 }}</td>
+ <td class="code"><pre>{{ var.1|pprint }}</pre></td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% else %}
+ <p>No GET data</p>
+ {% endif %}
+
+ <h3 id="post-info">POST</h3>
+ {% if filtered_POST %}
+ <table class="req">
+ <thead>
+ <tr>
+ <th>Variable</th>
+ <th>Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for var in filtered_POST.items %}
+ <tr>
+ <td>{{ var.0 }}</td>
+ <td class="code"><pre>{{ var.1|pprint }}</pre></td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% else %}
+ <p>No POST data</p>
+ {% endif %}
+ <h3 id="files-info">FILES</h3>
+ {% if request.FILES %}
+ <table class="req">
+ <thead>
+ <tr>
+ <th>Variable</th>
+ <th>Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for var in request.FILES.items %}
+ <tr>
+ <td>{{ var.0 }}</td>
+ <td class="code"><pre>{{ var.1|pprint }}</pre></td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% else %}
+ <p>No FILES data</p>
+ {% endif %}
+
+
+ <h3 id="cookie-info">COOKIES</h3>
+ {% if request.COOKIES %}
+ <table class="req">
+ <thead>
+ <tr>
+ <th>Variable</th>
+ <th>Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for var in request.COOKIES.items %}
+ <tr>
+ <td>{{ var.0 }}</td>
+ <td class="code"><pre>{{ var.1|pprint }}</pre></td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {% else %}
+ <p>No cookie data</p>
+ {% endif %}
+
+ <h3 id="meta-info">META</h3>
+ <table class="req">
+ <thead>
+ <tr>
+ <th>Variable</th>
+ <th>Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for var in request.META.items|dictsort:"0" %}
+ <tr>
+ <td>{{ var.0 }}</td>
+ <td class="code"><pre>{{ var.1|pprint }}</pre></td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+{% else %}
+ <p>Request data not supplied</p>
+{% endif %}
+
+ <h3 id="settings-info">Settings</h3>
+ <h4>Using settings module <code>{{ settings.SETTINGS_MODULE }}</code></h4>
+ <table class="req">
+ <thead>
+ <tr>
+ <th>Setting</th>
+ <th>Value</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for var in settings.items|dictsort:"0" %}
+ <tr>
+ <td>{{ var.0 }}</td>
+ <td class="code"><pre>{{ var.1|pprint }}</pre></td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+
+</div>
+{% if not is_email %}
+ <div id="explanation">
+ <p>
+ You're seeing this error because you have <code>DEBUG = True</code> in your
+ Django settings file. Change that to <code>False</code>, and Django will
+ display a standard 500 page.
+ </p>
+ </div>
+{% endif %}
+</body>
+</html>
+"""
+
+TECHNICAL_500_TEXT_TEMPLATE = """{% load firstof from future %}{% 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 TEMPLATE_LOADERS setting 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 500 page.
+"""
+
+TECHNICAL_404_TEMPLATE = """
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <title>Page not found at {{ request.path_info|escape }}</title>
+ <meta name="robots" content="NONE,NOARCHIVE">
+ <style type="text/css">
+ html * { padding:0; margin:0; }
+ body * { padding:10px 20px; }
+ body * * { padding:0; }
+ body { font:small sans-serif; background:#eee; }
+ body>div { border-bottom:1px solid #ddd; }
+ h1 { font-weight:normal; margin-bottom:.4em; }
+ h1 span { font-size:60%; color:#666; font-weight:normal; }
+ table { border:none; border-collapse: collapse; width:100%; }
+ td, th { vertical-align:top; padding:2px 3px; }
+ th { width:12em; text-align:right; color:#666; padding-right:.5em; }
+ #info { background:#f6f6f6; }
+ #info ol { margin: 0.5em 4em; }
+ #info ol li { font-family: monospace; }
+ #summary { background: #ffc; }
+ #explanation { background:#eee; border-bottom: 0px none; }
+ </style>
+</head>
+<body>
+ <div id="summary">
+ <h1>Page not found <span>(404)</span></h1>
+ <table class="meta">
+ <tr>
+ <th>Request Method:</th>
+ <td>{{ request.META.REQUEST_METHOD }}</td>
+ </tr>
+ <tr>
+ <th>Request URL:</th>
+ <td>{{ request.build_absolute_uri|escape }}</td>
+ </tr>
+ </table>
+ </div>
+ <div id="info">
+ {% if urlpatterns %}
+ <p>
+ Using the URLconf defined in <code>{{ urlconf }}</code>,
+ Django tried these URL patterns, in this order:
+ </p>
+ <ol>
+ {% for pattern in urlpatterns %}
+ <li>
+ {% for pat in pattern %}
+ {{ pat.regex.pattern }}
+ {% if forloop.last and pat.name %}[name='{{ pat.name }}']{% endif %}
+ {% endfor %}
+ </li>
+ {% endfor %}
+ </ol>
+ <p>The current URL, <code>{{ request_path|escape }}</code>, didn't match any of these.</p>
+ {% else %}
+ <p>{{ reason }}</p>
+ {% endif %}
+ </div>
+
+ <div id="explanation">
+ <p>
+ You're seeing this error because you have <code>DEBUG = True</code> in
+ your Django settings file. Change that to <code>False</code>, and Django
+ will display a standard 404 page.
+ </p>
+ </div>
+</body>
+</html>
+"""
+
+DEFAULT_URLCONF_TEMPLATE = """
+<!DOCTYPE html>
+<html lang="en"><head>
+ <meta http-equiv="content-type" content="text/html; charset=utf-8">
+ <meta name="robots" content="NONE,NOARCHIVE"><title>Welcome to Django</title>
+ <style type="text/css">
+ html * { padding:0; margin:0; }
+ body * { padding:10px 20px; }
+ body * * { padding:0; }
+ body { font:small sans-serif; }
+ body>div { border-bottom:1px solid #ddd; }
+ h1 { font-weight:normal; }
+ h2 { margin-bottom:.8em; }
+ h2 span { font-size:80%; color:#666; font-weight:normal; }
+ h3 { margin:1em 0 .5em 0; }
+ h4 { margin:0 0 .5em 0; font-weight: normal; }
+ table { border:1px solid #ccc; border-collapse: collapse; width:100%; background:white; }
+ tbody td, tbody th { vertical-align:top; padding:2px 3px; }
+ thead th { padding:1px 6px 1px 3px; background:#fefefe; text-align:left; font-weight:normal; font-size:11px; border:1px solid #ddd; }
+ tbody th { width:12em; text-align:right; color:#666; padding-right:.5em; }
+ #summary { background: #e0ebff; }
+ #summary h2 { font-weight: normal; color: #666; }
+ #explanation { background:#eee; }
+ #instructions { background:#f6f6f6; }
+ #summary table { border:none; background:transparent; }
+ </style>
+</head>
+
+<body>
+<div id="summary">
+ <h1>It worked!</h1>
+ <h2>Congratulations on your first Django-powered page.</h2>
+</div>
+
+<div id="instructions">
+ <p>
+ Of course, you haven't actually done any work yet.
+ Next, start your first app by running <code>python manage.py startapp [appname]</code>.
+ </p>
+</div>
+
+<div id="explanation">
+ <p>
+ You're seeing this message because you have <code>DEBUG = True</code> in your
+ Django settings file and you haven't configured any URLs. Get to work!
+ </p>
+</div>
+</body></html>
+"""
diff --git a/lib/python2.7/site-packages/django/views/decorators/__init__.py b/lib/python2.7/site-packages/django/views/decorators/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/decorators/__init__.py
diff --git a/lib/python2.7/site-packages/django/views/decorators/cache.py b/lib/python2.7/site-packages/django/views/decorators/cache.py
new file mode 100644
index 0000000..001e21c
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/decorators/cache.py
@@ -0,0 +1,55 @@
+from functools import wraps
+from django.utils.decorators import decorator_from_middleware_with_args, available_attrs
+from django.utils.cache import patch_cache_control, add_never_cache_headers
+from django.middleware.cache import CacheMiddleware
+
+
+def cache_page(*args, **kwargs):
+ """
+ Decorator for views that tries getting the page from the cache and
+ populates the cache if the page isn't in the cache yet.
+
+ The cache is keyed by the URL and some data from the headers.
+ Additionally there is the key prefix that is used to distinguish different
+ cache areas in a multi-site setup. You could use the
+ sites.get_current_site().domain, for example, as that is unique across a Django
+ project.
+
+ Additionally, all headers from the response's Vary header will be taken
+ into account on caching -- just like the middleware does.
+ """
+ # We also add some asserts to give better error messages in case people are
+ # using other ways to call cache_page that no longer work.
+ if len(args) != 1 or callable(args[0]):
+ raise TypeError("cache_page has a single mandatory positional argument: timeout")
+ cache_timeout = args[0]
+ cache_alias = kwargs.pop('cache', None)
+ key_prefix = kwargs.pop('key_prefix', None)
+ if kwargs:
+ raise TypeError("cache_page has two optional keyword arguments: cache and key_prefix")
+
+ return decorator_from_middleware_with_args(CacheMiddleware)(cache_timeout=cache_timeout, cache_alias=cache_alias, key_prefix=key_prefix)
+
+
+def cache_control(**kwargs):
+ def _cache_controller(viewfunc):
+ @wraps(viewfunc, assigned=available_attrs(viewfunc))
+ def _cache_controlled(request, *args, **kw):
+ response = viewfunc(request, *args, **kw)
+ patch_cache_control(response, **kwargs)
+ return response
+ return _cache_controlled
+ return _cache_controller
+
+
+def never_cache(view_func):
+ """
+ Decorator that adds headers to a response so that it will
+ never be cached.
+ """
+ @wraps(view_func, assigned=available_attrs(view_func))
+ def _wrapped_view_func(request, *args, **kwargs):
+ response = view_func(request, *args, **kwargs)
+ add_never_cache_headers(response)
+ return response
+ return _wrapped_view_func
diff --git a/lib/python2.7/site-packages/django/views/decorators/clickjacking.py b/lib/python2.7/site-packages/django/views/decorators/clickjacking.py
new file mode 100644
index 0000000..fcd7887
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/decorators/clickjacking.py
@@ -0,0 +1,64 @@
+from functools import wraps
+
+from django.utils.decorators import available_attrs
+
+
+def xframe_options_deny(view_func):
+ """
+ Modifies a view function so its response has the X-Frame-Options HTTP
+ header set to 'DENY' as long as the response doesn't already have that
+ header set.
+
+ e.g.
+
+ @xframe_options_deny
+ def some_view(request):
+ ...
+
+ """
+ def wrapped_view(*args, **kwargs):
+ resp = view_func(*args, **kwargs)
+ if resp.get('X-Frame-Options', None) is None:
+ resp['X-Frame-Options'] = 'DENY'
+ return resp
+ return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view)
+
+
+def xframe_options_sameorigin(view_func):
+ """
+ Modifies a view function so its response has the X-Frame-Options HTTP
+ header set to 'SAMEORIGIN' as long as the response doesn't already have
+ that header set.
+
+ e.g.
+
+ @xframe_options_sameorigin
+ def some_view(request):
+ ...
+
+ """
+ def wrapped_view(*args, **kwargs):
+ resp = view_func(*args, **kwargs)
+ if resp.get('X-Frame-Options', None) is None:
+ resp['X-Frame-Options'] = 'SAMEORIGIN'
+ return resp
+ return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view)
+
+
+def xframe_options_exempt(view_func):
+ """
+ Modifies a view function by setting a response variable that instructs
+ XFrameOptionsMiddleware to NOT set the X-Frame-Options HTTP header.
+
+ e.g.
+
+ @xframe_options_exempt
+ def some_view(request):
+ ...
+
+ """
+ def wrapped_view(*args, **kwargs):
+ resp = view_func(*args, **kwargs)
+ resp.xframe_options_exempt = True
+ return resp
+ return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view)
diff --git a/lib/python2.7/site-packages/django/views/decorators/csrf.py b/lib/python2.7/site-packages/django/views/decorators/csrf.py
new file mode 100644
index 0000000..1ebed2a
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/decorators/csrf.py
@@ -0,0 +1,59 @@
+from django.middleware.csrf import CsrfViewMiddleware, get_token
+from django.utils.decorators import decorator_from_middleware, available_attrs
+from functools import wraps
+
+csrf_protect = decorator_from_middleware(CsrfViewMiddleware)
+csrf_protect.__name__ = "csrf_protect"
+csrf_protect.__doc__ = """
+This decorator adds CSRF protection in exactly the same way as
+CsrfViewMiddleware, but it can be used on a per view basis. Using both, or
+using the decorator multiple times, is harmless and efficient.
+"""
+
+
+class _EnsureCsrfToken(CsrfViewMiddleware):
+ # We need this to behave just like the CsrfViewMiddleware, but not reject
+ # requests or log warnings.
+ def _reject(self, request, reason):
+ return None
+
+
+requires_csrf_token = decorator_from_middleware(_EnsureCsrfToken)
+requires_csrf_token.__name__ = 'requires_csrf_token'
+requires_csrf_token.__doc__ = """
+Use this decorator on views that need a correct csrf_token available to
+RequestContext, but without the CSRF protection that csrf_protect
+enforces.
+"""
+
+
+class _EnsureCsrfCookie(CsrfViewMiddleware):
+ def _reject(self, request, reason):
+ return None
+
+ def process_view(self, request, callback, callback_args, callback_kwargs):
+ retval = super(_EnsureCsrfCookie, self).process_view(request, callback, callback_args, callback_kwargs)
+ # Forces process_response to send the cookie
+ get_token(request)
+ return retval
+
+
+ensure_csrf_cookie = decorator_from_middleware(_EnsureCsrfCookie)
+ensure_csrf_cookie.__name__ = 'ensure_csrf_cookie'
+ensure_csrf_cookie.__doc__ = """
+Use this decorator to ensure that a view sets a CSRF cookie, whether or not it
+uses the csrf_token template tag, or the CsrfViewMiddleware is used.
+"""
+
+
+def csrf_exempt(view_func):
+ """
+ Marks a view function as being exempt from the CSRF view protection.
+ """
+ # We could just do view_func.csrf_exempt = True, but decorators
+ # are nicer if they don't have side-effects, so we return a new
+ # function.
+ def wrapped_view(*args, **kwargs):
+ return view_func(*args, **kwargs)
+ wrapped_view.csrf_exempt = True
+ return wraps(view_func, assigned=available_attrs(view_func))(wrapped_view)
diff --git a/lib/python2.7/site-packages/django/views/decorators/debug.py b/lib/python2.7/site-packages/django/views/decorators/debug.py
new file mode 100644
index 0000000..a611981
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/decorators/debug.py
@@ -0,0 +1,77 @@
+import functools
+
+from django.http import HttpRequest
+
+
+def sensitive_variables(*variables):
+ """
+ Indicates which variables used in the decorated function are sensitive, so
+ that those variables can later be treated in a special way, for example
+ by hiding them when logging unhandled exceptions.
+
+ Two forms are accepted:
+
+ * with specified variable names:
+
+ @sensitive_variables('user', 'password', 'credit_card')
+ def my_function(user):
+ password = user.pass_word
+ credit_card = user.credit_card_number
+ ...
+
+ * without any specified variable names, in which case it is assumed that
+ all variables are considered sensitive:
+
+ @sensitive_variables()
+ def my_function()
+ ...
+ """
+ def decorator(func):
+ @functools.wraps(func)
+ def sensitive_variables_wrapper(*func_args, **func_kwargs):
+ if variables:
+ sensitive_variables_wrapper.sensitive_variables = variables
+ else:
+ sensitive_variables_wrapper.sensitive_variables = '__ALL__'
+ return func(*func_args, **func_kwargs)
+ return sensitive_variables_wrapper
+ return decorator
+
+
+def sensitive_post_parameters(*parameters):
+ """
+ Indicates which POST parameters used in the decorated view are sensitive,
+ so that those parameters can later be treated in a special way, for example
+ by hiding them when logging unhandled exceptions.
+
+ Two forms are accepted:
+
+ * with specified parameters:
+
+ @sensitive_post_parameters('password', 'credit_card')
+ def my_view(request):
+ pw = request.POST['password']
+ cc = request.POST['credit_card']
+ ...
+
+ * without any specified parameters, in which case it is assumed that
+ all parameters are considered sensitive:
+
+ @sensitive_post_parameters()
+ def my_view(request)
+ ...
+ """
+ def decorator(view):
+ @functools.wraps(view)
+ def sensitive_post_parameters_wrapper(request, *args, **kwargs):
+ assert isinstance(request, HttpRequest), (
+ "sensitive_post_parameters didn't receive an HttpRequest. If you "
+ "are decorating a classmethod, be sure to use @method_decorator."
+ )
+ if parameters:
+ request.sensitive_post_parameters = parameters
+ else:
+ request.sensitive_post_parameters = '__ALL__'
+ return view(request, *args, **kwargs)
+ return sensitive_post_parameters_wrapper
+ return decorator
diff --git a/lib/python2.7/site-packages/django/views/decorators/gzip.py b/lib/python2.7/site-packages/django/views/decorators/gzip.py
new file mode 100644
index 0000000..f5b009d
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/decorators/gzip.py
@@ -0,0 +1,5 @@
+from django.utils.decorators import decorator_from_middleware
+from django.middleware.gzip import GZipMiddleware
+
+gzip_page = decorator_from_middleware(GZipMiddleware)
+gzip_page.__doc__ = "Decorator for views that gzips pages if the client supports it."
diff --git a/lib/python2.7/site-packages/django/views/decorators/http.py b/lib/python2.7/site-packages/django/views/decorators/http.py
new file mode 100644
index 0000000..410979e
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/decorators/http.py
@@ -0,0 +1,166 @@
+"""
+Decorators for views based on HTTP headers.
+"""
+
+import logging
+from calendar import timegm
+from functools import wraps
+
+from django.utils.decorators import decorator_from_middleware, available_attrs
+from django.utils.http import http_date, parse_http_date_safe, parse_etags, quote_etag
+from django.middleware.http import ConditionalGetMiddleware
+from django.http import HttpResponseNotAllowed, HttpResponseNotModified, HttpResponse
+
+conditional_page = decorator_from_middleware(ConditionalGetMiddleware)
+
+logger = logging.getLogger('django.request')
+
+
+def require_http_methods(request_method_list):
+ """
+ Decorator to make a view only accept particular request methods. Usage::
+
+ @require_http_methods(["GET", "POST"])
+ def my_view(request):
+ # I can assume now that only GET or POST requests make it this far
+ # ...
+
+ Note that request methods should be in uppercase.
+ """
+ def decorator(func):
+ @wraps(func, assigned=available_attrs(func))
+ def inner(request, *args, **kwargs):
+ if request.method not in request_method_list:
+ logger.warning('Method Not Allowed (%s): %s', request.method, request.path,
+ extra={
+ 'status_code': 405,
+ 'request': request
+ }
+ )
+ return HttpResponseNotAllowed(request_method_list)
+ return func(request, *args, **kwargs)
+ return inner
+ return decorator
+
+require_GET = require_http_methods(["GET"])
+require_GET.__doc__ = "Decorator to require that a view only accept the GET method."
+
+require_POST = require_http_methods(["POST"])
+require_POST.__doc__ = "Decorator to require that a view only accept the POST method."
+
+require_safe = require_http_methods(["GET", "HEAD"])
+require_safe.__doc__ = "Decorator to require that a view only accept safe methods: GET and HEAD."
+
+def condition(etag_func=None, last_modified_func=None):
+ """
+ Decorator to support conditional retrieval (or change) for a view
+ function.
+
+ The parameters are callables to compute the ETag and last modified time for
+ the requested resource, respectively. The callables are passed the same
+ parameters as the view itself. The Etag function should return a string (or
+ None if the resource doesn't exist), whilst the last_modified function
+ should return a datetime object (or None if the resource doesn't exist).
+
+ If both parameters are provided, all the preconditions must be met before
+ the view is processed.
+
+ This decorator will either pass control to the wrapped view function or
+ return an HTTP 304 response (unmodified) or 412 response (preconditions
+ failed), depending upon the request method.
+
+ Any behavior marked as "undefined" in the HTTP spec (e.g. If-none-match
+ plus If-modified-since headers) will result in the view function being
+ called.
+ """
+ def decorator(func):
+ @wraps(func, assigned=available_attrs(func))
+ def inner(request, *args, **kwargs):
+ # Get HTTP request headers
+ if_modified_since = request.META.get("HTTP_IF_MODIFIED_SINCE")
+ if if_modified_since:
+ if_modified_since = parse_http_date_safe(if_modified_since)
+ if_none_match = request.META.get("HTTP_IF_NONE_MATCH")
+ if_match = request.META.get("HTTP_IF_MATCH")
+ if if_none_match or if_match:
+ # There can be more than one ETag in the request, so we
+ # consider the list of values.
+ try:
+ etags = parse_etags(if_none_match or if_match)
+ except ValueError:
+ # In case of invalid etag ignore all ETag headers.
+ # Apparently Opera sends invalidly quoted headers at times
+ # (we should be returning a 400 response, but that's a
+ # little extreme) -- this is Django bug #10681.
+ if_none_match = None
+ if_match = None
+
+ # Compute values (if any) for the requested resource.
+ if etag_func:
+ res_etag = etag_func(request, *args, **kwargs)
+ else:
+ res_etag = None
+ if last_modified_func:
+ dt = last_modified_func(request, *args, **kwargs)
+ if dt:
+ res_last_modified = timegm(dt.utctimetuple())
+ else:
+ res_last_modified = None
+ else:
+ res_last_modified = None
+
+ response = None
+ if not ((if_match and (if_modified_since or if_none_match)) or
+ (if_match and if_none_match)):
+ # We only get here if no undefined combinations of headers are
+ # specified.
+ if ((if_none_match and (res_etag in etags or
+ "*" in etags and res_etag)) and
+ (not if_modified_since or
+ (res_last_modified and if_modified_since and
+ res_last_modified <= if_modified_since))):
+ if request.method in ("GET", "HEAD"):
+ response = HttpResponseNotModified()
+ else:
+ logger.warning('Precondition Failed: %s', request.path,
+ extra={
+ 'status_code': 412,
+ 'request': request
+ }
+ )
+ response = HttpResponse(status=412)
+ elif if_match and ((not res_etag and "*" in etags) or
+ (res_etag and res_etag not in etags)):
+ logger.warning('Precondition Failed: %s', request.path,
+ extra={
+ 'status_code': 412,
+ 'request': request
+ }
+ )
+ response = HttpResponse(status=412)
+ elif (not if_none_match and request.method == "GET" and
+ res_last_modified and if_modified_since and
+ res_last_modified <= if_modified_since):
+ response = HttpResponseNotModified()
+
+ if response is None:
+ response = func(request, *args, **kwargs)
+
+ # Set relevant headers on the response if they don't already exist.
+ if res_last_modified and not response.has_header('Last-Modified'):
+ response['Last-Modified'] = http_date(res_last_modified)
+ if res_etag and not response.has_header('ETag'):
+ response['ETag'] = quote_etag(res_etag)
+
+ return response
+
+ return inner
+ return decorator
+
+# Shortcut decorators for common cases based on ETag or Last-Modified only
+def etag(etag_func):
+ return condition(etag_func=etag_func)
+
+def last_modified(last_modified_func):
+ return condition(last_modified_func=last_modified_func)
+
diff --git a/lib/python2.7/site-packages/django/views/decorators/vary.py b/lib/python2.7/site-packages/django/views/decorators/vary.py
new file mode 100644
index 0000000..cd2f9c0
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/decorators/vary.py
@@ -0,0 +1,39 @@
+from functools import wraps
+from django.utils.cache import patch_vary_headers
+from django.utils.decorators import available_attrs
+
+def vary_on_headers(*headers):
+ """
+ A view decorator that adds the specified headers to the Vary header of the
+ response. Usage:
+
+ @vary_on_headers('Cookie', 'Accept-language')
+ def index(request):
+ ...
+
+ Note that the header names are not case-sensitive.
+ """
+ def decorator(func):
+ @wraps(func, assigned=available_attrs(func))
+ def inner_func(*args, **kwargs):
+ response = func(*args, **kwargs)
+ patch_vary_headers(response, headers)
+ return response
+ return inner_func
+ return decorator
+
+def vary_on_cookie(func):
+ """
+ A view decorator that adds "Cookie" to the Vary header of a response. This
+ indicates that a page's contents depends on cookies. Usage:
+
+ @vary_on_cookie
+ def index(request):
+ ...
+ """
+ @wraps(func, assigned=available_attrs(func))
+ def inner_func(*args, **kwargs):
+ response = func(*args, **kwargs)
+ patch_vary_headers(response, ('Cookie',))
+ return response
+ return inner_func
diff --git a/lib/python2.7/site-packages/django/views/defaults.py b/lib/python2.7/site-packages/django/views/defaults.py
new file mode 100644
index 0000000..d531f22
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/defaults.py
@@ -0,0 +1,91 @@
+import warnings
+
+from django import http
+from django.template import (Context, RequestContext,
+ loader, Template, TemplateDoesNotExist)
+from django.views.decorators.csrf import requires_csrf_token
+
+
+# This can be called when CsrfViewMiddleware.process_view has not run,
+# therefore need @requires_csrf_token in case the template needs
+# {% csrf_token %}.
+@requires_csrf_token
+def page_not_found(request, template_name='404.html'):
+ """
+ Default 404 handler.
+
+ Templates: :template:`404.html`
+ Context:
+ request_path
+ The path of the requested URL (e.g., '/app/pages/bad_page/')
+ """
+ try:
+ template = loader.get_template(template_name)
+ content_type = None # Django will use DEFAULT_CONTENT_TYPE
+ except TemplateDoesNotExist:
+ template = Template(
+ '<h1>Not Found</h1>'
+ '<p>The requested URL {{ request_path }} was not found on this server.</p>')
+ content_type = 'text/html'
+ body = template.render(RequestContext(request, {'request_path': request.path}))
+ return http.HttpResponseNotFound(body, content_type=content_type)
+
+
+@requires_csrf_token
+def server_error(request, template_name='500.html'):
+ """
+ 500 error handler.
+
+ Templates: :template:`500.html`
+ Context: None
+ """
+ try:
+ template = loader.get_template(template_name)
+ except TemplateDoesNotExist:
+ return http.HttpResponseServerError('<h1>Server Error (500)</h1>', content_type='text/html')
+ return http.HttpResponseServerError(template.render(Context({})))
+
+
+@requires_csrf_token
+def bad_request(request, template_name='400.html'):
+ """
+ 400 error handler.
+
+ Templates: :template:`400.html`
+ Context: None
+ """
+ try:
+ template = loader.get_template(template_name)
+ except TemplateDoesNotExist:
+ return http.HttpResponseBadRequest('<h1>Bad Request (400)</h1>', content_type='text/html')
+ return http.HttpResponseBadRequest(template.render(Context({})))
+
+
+# This can be called when CsrfViewMiddleware.process_view has not run,
+# therefore need @requires_csrf_token in case the template needs
+# {% csrf_token %}.
+@requires_csrf_token
+def permission_denied(request, template_name='403.html'):
+ """
+ Permission denied (403) handler.
+
+ Templates: :template:`403.html`
+ Context: None
+
+ If the template does not exist, an Http403 response containing the text
+ "403 Forbidden" (as per RFC 2616) will be returned.
+ """
+ try:
+ template = loader.get_template(template_name)
+ except TemplateDoesNotExist:
+ return http.HttpResponseForbidden('<h1>403 Forbidden</h1>', content_type='text/html')
+ return http.HttpResponseForbidden(template.render(RequestContext(request)))
+
+
+def shortcut(request, content_type_id, object_id):
+ warnings.warn(
+ "django.views.defaults.shortcut will be removed in Django 1.8. "
+ "Import it from django.contrib.contenttypes.views instead.",
+ PendingDeprecationWarning, stacklevel=2)
+ from django.contrib.contenttypes.views import shortcut as real_shortcut
+ return real_shortcut(request, content_type_id, object_id)
diff --git a/lib/python2.7/site-packages/django/views/generic/__init__.py b/lib/python2.7/site-packages/django/views/generic/__init__.py
new file mode 100644
index 0000000..1a98067
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/generic/__init__.py
@@ -0,0 +1,12 @@
+from django.views.generic.base import View, TemplateView, RedirectView
+from django.views.generic.dates import (ArchiveIndexView, YearArchiveView, MonthArchiveView,
+ WeekArchiveView, DayArchiveView, TodayArchiveView,
+ DateDetailView)
+from django.views.generic.detail import DetailView
+from django.views.generic.edit import FormView, CreateView, UpdateView, DeleteView
+from django.views.generic.list import ListView
+
+
+class GenericViewError(Exception):
+ """A problem in a generic view."""
+ pass
diff --git a/lib/python2.7/site-packages/django/views/generic/base.py b/lib/python2.7/site-packages/django/views/generic/base.py
new file mode 100644
index 0000000..2487ccb
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/generic/base.py
@@ -0,0 +1,219 @@
+from __future__ import unicode_literals
+
+import logging
+from functools import update_wrapper
+
+from django import http
+from django.core.exceptions import ImproperlyConfigured
+from django.core.urlresolvers import reverse, NoReverseMatch
+from django.template.response import TemplateResponse
+from django.utils.decorators import classonlymethod
+from django.utils import six
+
+logger = logging.getLogger('django.request')
+
+
+class ContextMixin(object):
+ """
+ A default context mixin that passes the keyword arguments received by
+ get_context_data as the template context.
+ """
+
+ def get_context_data(self, **kwargs):
+ if 'view' not in kwargs:
+ kwargs['view'] = self
+ return kwargs
+
+
+class View(object):
+ """
+ Intentionally simple parent class for all views. Only implements
+ dispatch-by-method and simple sanity checking.
+ """
+
+ http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace']
+
+ def __init__(self, **kwargs):
+ """
+ Constructor. Called in the URLconf; can contain helpful extra
+ keyword arguments, and other things.
+ """
+ # Go through keyword arguments, and either save their values to our
+ # instance, or raise an error.
+ for key, value in six.iteritems(kwargs):
+ setattr(self, key, value)
+
+ @classonlymethod
+ def as_view(cls, **initkwargs):
+ """
+ Main entry point for a request-response process.
+ """
+ # sanitize keyword arguments
+ for key in initkwargs:
+ if key in cls.http_method_names:
+ raise TypeError("You tried to pass in the %s method name as a "
+ "keyword argument to %s(). Don't do that."
+ % (key, cls.__name__))
+ if not hasattr(cls, key):
+ raise TypeError("%s() received an invalid keyword %r. as_view "
+ "only accepts arguments that are already "
+ "attributes of the class." % (cls.__name__, key))
+
+ def view(request, *args, **kwargs):
+ self = cls(**initkwargs)
+ if hasattr(self, 'get') and not hasattr(self, 'head'):
+ self.head = self.get
+ self.request = request
+ self.args = args
+ self.kwargs = kwargs
+ return self.dispatch(request, *args, **kwargs)
+
+ # take name and docstring from class
+ update_wrapper(view, cls, updated=())
+
+ # and possible attributes set by decorators
+ # like csrf_exempt from dispatch
+ update_wrapper(view, cls.dispatch, assigned=())
+ return view
+
+ def dispatch(self, request, *args, **kwargs):
+ # Try to dispatch to the right method; if a method doesn't exist,
+ # defer to the error handler. Also defer to the error handler if the
+ # request method isn't on the approved list.
+ if request.method.lower() in self.http_method_names:
+ handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
+ else:
+ handler = self.http_method_not_allowed
+ return handler(request, *args, **kwargs)
+
+ def http_method_not_allowed(self, request, *args, **kwargs):
+ logger.warning('Method Not Allowed (%s): %s', request.method, request.path,
+ extra={
+ 'status_code': 405,
+ 'request': self.request
+ }
+ )
+ return http.HttpResponseNotAllowed(self._allowed_methods())
+
+ def options(self, request, *args, **kwargs):
+ """
+ Handles responding to requests for the OPTIONS HTTP verb.
+ """
+ response = http.HttpResponse()
+ response['Allow'] = ', '.join(self._allowed_methods())
+ response['Content-Length'] = '0'
+ return response
+
+ def _allowed_methods(self):
+ return [m.upper() for m in self.http_method_names if hasattr(self, m)]
+
+
+class TemplateResponseMixin(object):
+ """
+ A mixin that can be used to render a template.
+ """
+ template_name = None
+ response_class = TemplateResponse
+ content_type = None
+
+ def render_to_response(self, context, **response_kwargs):
+ """
+ Returns a response, using the `response_class` for this
+ view, with a template rendered with the given context.
+
+ If any keyword arguments are provided, they will be
+ passed to the constructor of the response class.
+ """
+ response_kwargs.setdefault('content_type', self.content_type)
+ return self.response_class(
+ request = self.request,
+ template = self.get_template_names(),
+ context = context,
+ **response_kwargs
+ )
+
+ def get_template_names(self):
+ """
+ Returns a list of template names to be used for the request. Must return
+ a list. May not be called if render_to_response is overridden.
+ """
+ if self.template_name is None:
+ raise ImproperlyConfigured(
+ "TemplateResponseMixin requires either a definition of "
+ "'template_name' or an implementation of 'get_template_names()'")
+ else:
+ return [self.template_name]
+
+
+class TemplateView(TemplateResponseMixin, ContextMixin, View):
+ """
+ A view that renders a template. This view will also pass into the context
+ any keyword arguments passed by the url conf.
+ """
+ def get(self, request, *args, **kwargs):
+ context = self.get_context_data(**kwargs)
+ return self.render_to_response(context)
+
+
+class RedirectView(View):
+ """
+ A view that provides a redirect on any GET request.
+ """
+ permanent = True
+ url = None
+ pattern_name = None
+ query_string = False
+
+ def get_redirect_url(self, *args, **kwargs):
+ """
+ Return the URL redirect to. Keyword arguments from the
+ URL pattern match generating the redirect request
+ are provided as kwargs to this method.
+ """
+ if self.url:
+ url = self.url % kwargs
+ elif self.pattern_name:
+ try:
+ url = reverse(self.pattern_name, args=args, kwargs=kwargs)
+ except NoReverseMatch:
+ return None
+ else:
+ return None
+
+ args = self.request.META.get('QUERY_STRING', '')
+ if args and self.query_string:
+ url = "%s?%s" % (url, args)
+ return url
+
+ def get(self, request, *args, **kwargs):
+ url = self.get_redirect_url(*args, **kwargs)
+ if url:
+ if self.permanent:
+ return http.HttpResponsePermanentRedirect(url)
+ else:
+ return http.HttpResponseRedirect(url)
+ else:
+ logger.warning('Gone: %s', self.request.path,
+ extra={
+ 'status_code': 410,
+ 'request': self.request
+ })
+ return http.HttpResponseGone()
+
+ def head(self, request, *args, **kwargs):
+ return self.get(request, *args, **kwargs)
+
+ def post(self, request, *args, **kwargs):
+ return self.get(request, *args, **kwargs)
+
+ def options(self, request, *args, **kwargs):
+ return self.get(request, *args, **kwargs)
+
+ def delete(self, request, *args, **kwargs):
+ return self.get(request, *args, **kwargs)
+
+ def put(self, request, *args, **kwargs):
+ return self.get(request, *args, **kwargs)
+
+ def patch(self, request, *args, **kwargs):
+ return self.get(request, *args, **kwargs)
diff --git a/lib/python2.7/site-packages/django/views/generic/dates.py b/lib/python2.7/site-packages/django/views/generic/dates.py
new file mode 100644
index 0000000..1b8ad3e
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/generic/dates.py
@@ -0,0 +1,785 @@
+from __future__ import unicode_literals
+
+import datetime
+from django.conf import settings
+from django.db import models
+from django.core.exceptions import ImproperlyConfigured
+from django.http import Http404
+from django.utils.encoding import force_str, force_text
+from django.utils.functional import cached_property
+from django.utils.translation import ugettext as _
+from django.utils import timezone
+from django.views.generic.base import View
+from django.views.generic.detail import BaseDetailView, SingleObjectTemplateResponseMixin
+from django.views.generic.list import MultipleObjectMixin, MultipleObjectTemplateResponseMixin
+
+class YearMixin(object):
+ """
+ Mixin for views manipulating year-based data.
+ """
+ year_format = '%Y'
+ year = None
+
+ def get_year_format(self):
+ """
+ Get a year format string in strptime syntax to be used to parse the
+ year from url variables.
+ """
+ return self.year_format
+
+ def get_year(self):
+ """
+ Return the year for which this view should display data.
+ """
+ year = self.year
+ if year is None:
+ try:
+ year = self.kwargs['year']
+ except KeyError:
+ try:
+ year = self.request.GET['year']
+ except KeyError:
+ raise Http404(_("No year specified"))
+ return year
+
+ def get_next_year(self, date):
+ """
+ Get the next valid year.
+ """
+ return _get_next_prev(self, date, is_previous=False, period='year')
+
+ def get_previous_year(self, date):
+ """
+ Get the previous valid year.
+ """
+ return _get_next_prev(self, date, is_previous=True, period='year')
+
+ def _get_next_year(self, date):
+ """
+ Return the start date of the next interval.
+
+ The interval is defined by start date <= item date < next start date.
+ """
+ return date.replace(year=date.year + 1, month=1, day=1)
+
+ def _get_current_year(self, date):
+ """
+ Return the start date of the current interval.
+ """
+ return date.replace(month=1, day=1)
+
+
+class MonthMixin(object):
+ """
+ Mixin for views manipulating month-based data.
+ """
+ month_format = '%b'
+ month = None
+
+ def get_month_format(self):
+ """
+ Get a month format string in strptime syntax to be used to parse the
+ month from url variables.
+ """
+ return self.month_format
+
+ def get_month(self):
+ """
+ Return the month for which this view should display data.
+ """
+ month = self.month
+ if month is None:
+ try:
+ month = self.kwargs['month']
+ except KeyError:
+ try:
+ month = self.request.GET['month']
+ except KeyError:
+ raise Http404(_("No month specified"))
+ return month
+
+ def get_next_month(self, date):
+ """
+ Get the next valid month.
+ """
+ return _get_next_prev(self, date, is_previous=False, period='month')
+
+ def get_previous_month(self, date):
+ """
+ Get the previous valid month.
+ """
+ return _get_next_prev(self, date, is_previous=True, period='month')
+
+ def _get_next_month(self, date):
+ """
+ Return the start date of the next interval.
+
+ The interval is defined by start date <= item date < next start date.
+ """
+ if date.month == 12:
+ return date.replace(year=date.year + 1, month=1, day=1)
+ else:
+ return date.replace(month=date.month + 1, day=1)
+
+ def _get_current_month(self, date):
+ """
+ Return the start date of the previous interval.
+ """
+ return date.replace(day=1)
+
+
+class DayMixin(object):
+ """
+ Mixin for views manipulating day-based data.
+ """
+ day_format = '%d'
+ day = None
+
+ def get_day_format(self):
+ """
+ Get a day format string in strptime syntax to be used to parse the day
+ from url variables.
+ """
+ return self.day_format
+
+ def get_day(self):
+ """
+ Return the day for which this view should display data.
+ """
+ day = self.day
+ if day is None:
+ try:
+ day = self.kwargs['day']
+ except KeyError:
+ try:
+ day = self.request.GET['day']
+ except KeyError:
+ raise Http404(_("No day specified"))
+ return day
+
+ def get_next_day(self, date):
+ """
+ Get the next valid day.
+ """
+ return _get_next_prev(self, date, is_previous=False, period='day')
+
+ def get_previous_day(self, date):
+ """
+ Get the previous valid day.
+ """
+ return _get_next_prev(self, date, is_previous=True, period='day')
+
+ def _get_next_day(self, date):
+ """
+ Return the start date of the next interval.
+
+ The interval is defined by start date <= item date < next start date.
+ """
+ return date + datetime.timedelta(days=1)
+
+ def _get_current_day(self, date):
+ """
+ Return the start date of the current interval.
+ """
+ return date
+
+
+class WeekMixin(object):
+ """
+ Mixin for views manipulating week-based data.
+ """
+ week_format = '%U'
+ week = None
+
+ def get_week_format(self):
+ """
+ Get a week format string in strptime syntax to be used to parse the
+ week from url variables.
+ """
+ return self.week_format
+
+ def get_week(self):
+ """
+ Return the week for which this view should display data
+ """
+ week = self.week
+ if week is None:
+ try:
+ week = self.kwargs['week']
+ except KeyError:
+ try:
+ week = self.request.GET['week']
+ except KeyError:
+ raise Http404(_("No week specified"))
+ return week
+
+ def get_next_week(self, date):
+ """
+ Get the next valid week.
+ """
+ return _get_next_prev(self, date, is_previous=False, period='week')
+
+ def get_previous_week(self, date):
+ """
+ Get the previous valid week.
+ """
+ return _get_next_prev(self, date, is_previous=True, period='week')
+
+ def _get_next_week(self, date):
+ """
+ Return the start date of the next interval.
+
+ The interval is defined by start date <= item date < next start date.
+ """
+ return date + datetime.timedelta(days=7 - self._get_weekday(date))
+
+ def _get_current_week(self, date):
+ """
+ Return the start date of the current interval.
+ """
+ return date - datetime.timedelta(self._get_weekday(date))
+
+ def _get_weekday(self, date):
+ """
+ Return the weekday for a given date.
+
+ The first day according to the week format is 0 and the last day is 6.
+ """
+ week_format = self.get_week_format()
+ if week_format == '%W': # week starts on Monday
+ return date.weekday()
+ elif week_format == '%U': # week starts on Sunday
+ return (date.weekday() + 1) % 7
+ else:
+ raise ValueError("unknown week format: %s" % week_format)
+
+
+class DateMixin(object):
+ """
+ Mixin class for views manipulating date-based data.
+ """
+ date_field = None
+ allow_future = False
+
+ def get_date_field(self):
+ """
+ Get the name of the date field to be used to filter by.
+ """
+ if self.date_field is None:
+ raise ImproperlyConfigured("%s.date_field is required." % self.__class__.__name__)
+ return self.date_field
+
+ def get_allow_future(self):
+ """
+ Returns `True` if the view should be allowed to display objects from
+ the future.
+ """
+ return self.allow_future
+
+ # Note: the following three methods only work in subclasses that also
+ # inherit SingleObjectMixin or MultipleObjectMixin.
+
+ @cached_property
+ def uses_datetime_field(self):
+ """
+ Return `True` if the date field is a `DateTimeField` and `False`
+ if it's a `DateField`.
+ """
+ model = self.get_queryset().model if self.model is None else self.model
+ field = model._meta.get_field(self.get_date_field())
+ return isinstance(field, models.DateTimeField)
+
+ def _make_date_lookup_arg(self, value):
+ """
+ Convert a date into a datetime when the date field is a DateTimeField.
+
+ When time zone support is enabled, `date` is assumed to be in the
+ current time zone, so that displayed items are consistent with the URL.
+ """
+ if self.uses_datetime_field:
+ value = datetime.datetime.combine(value, datetime.time.min)
+ if settings.USE_TZ:
+ value = timezone.make_aware(value, timezone.get_current_timezone())
+ return value
+
+ def _make_single_date_lookup(self, date):
+ """
+ Get the lookup kwargs for filtering on a single date.
+
+ If the date field is a DateTimeField, we can't just filter on
+ date_field=date because that doesn't take the time into account.
+ """
+ date_field = self.get_date_field()
+ if self.uses_datetime_field:
+ since = self._make_date_lookup_arg(date)
+ until = self._make_date_lookup_arg(date + datetime.timedelta(days=1))
+ return {
+ '%s__gte' % date_field: since,
+ '%s__lt' % date_field: until,
+ }
+ else:
+ # Skip self._make_date_lookup_arg, it's a no-op in this branch.
+ return {date_field: date}
+
+
+class BaseDateListView(MultipleObjectMixin, DateMixin, View):
+ """
+ Abstract base class for date-based views displaying a list of objects.
+ """
+ allow_empty = False
+ date_list_period = 'year'
+
+ def get(self, request, *args, **kwargs):
+ self.date_list, self.object_list, extra_context = self.get_dated_items()
+ context = self.get_context_data(object_list=self.object_list,
+ date_list=self.date_list)
+ context.update(extra_context)
+ return self.render_to_response(context)
+
+ def get_dated_items(self):
+ """
+ Obtain the list of dates and items.
+ """
+ raise NotImplementedError('A DateView must provide an implementation of get_dated_items()')
+
+ def get_dated_queryset(self, ordering=None, **lookup):
+ """
+ Get a queryset properly filtered according to `allow_future` and any
+ extra lookup kwargs.
+ """
+ qs = self.get_queryset().filter(**lookup)
+ date_field = self.get_date_field()
+ allow_future = self.get_allow_future()
+ allow_empty = self.get_allow_empty()
+ paginate_by = self.get_paginate_by(qs)
+
+ if ordering is not None:
+ qs = qs.order_by(ordering)
+
+ if not allow_future:
+ now = timezone.now() if self.uses_datetime_field else timezone_today()
+ qs = qs.filter(**{'%s__lte' % date_field: now})
+
+ if not allow_empty:
+ # When pagination is enabled, it's better to do a cheap query
+ # than to load the unpaginated queryset in memory.
+ is_empty = len(qs) == 0 if paginate_by is None else not qs.exists()
+ if is_empty:
+ raise Http404(_("No %(verbose_name_plural)s available") % {
+ 'verbose_name_plural': force_text(qs.model._meta.verbose_name_plural)
+ })
+
+ return qs
+
+ def get_date_list_period(self):
+ """
+ Get the aggregation period for the list of dates: 'year', 'month', or 'day'.
+ """
+ return self.date_list_period
+
+ def get_date_list(self, queryset, date_type=None, ordering='ASC'):
+ """
+ Get a date list by calling `queryset.dates/datetimes()`, checking
+ along the way for empty lists that aren't allowed.
+ """
+ date_field = self.get_date_field()
+ allow_empty = self.get_allow_empty()
+ if date_type is None:
+ date_type = self.get_date_list_period()
+
+ if self.uses_datetime_field:
+ date_list = queryset.datetimes(date_field, date_type, ordering)
+ else:
+ date_list = queryset.dates(date_field, date_type, ordering)
+ if date_list is not None and not date_list and not allow_empty:
+ name = force_text(queryset.model._meta.verbose_name_plural)
+ raise Http404(_("No %(verbose_name_plural)s available") %
+ {'verbose_name_plural': name})
+
+ return date_list
+
+
+class BaseArchiveIndexView(BaseDateListView):
+ """
+ Base class for archives of date-based items.
+
+ Requires a response mixin.
+ """
+ context_object_name = 'latest'
+
+ def get_dated_items(self):
+ """
+ Return (date_list, items, extra_context) for this request.
+ """
+ qs = self.get_dated_queryset(ordering='-%s' % self.get_date_field())
+ date_list = self.get_date_list(qs, ordering='DESC')
+
+ if not date_list:
+ qs = qs.none()
+
+ return (date_list, qs, {})
+
+
+class ArchiveIndexView(MultipleObjectTemplateResponseMixin, BaseArchiveIndexView):
+ """
+ Top-level archive of date-based items.
+ """
+ template_name_suffix = '_archive'
+
+
+class BaseYearArchiveView(YearMixin, BaseDateListView):
+ """
+ List of objects published in a given year.
+ """
+ date_list_period = 'month'
+ make_object_list = False
+
+ def get_dated_items(self):
+ """
+ Return (date_list, items, extra_context) for this request.
+ """
+ year = self.get_year()
+
+ date_field = self.get_date_field()
+ date = _date_from_string(year, self.get_year_format())
+
+ since = self._make_date_lookup_arg(date)
+ until = self._make_date_lookup_arg(self._get_next_year(date))
+ lookup_kwargs = {
+ '%s__gte' % date_field: since,
+ '%s__lt' % date_field: until,
+ }
+
+ qs = self.get_dated_queryset(ordering='-%s' % date_field, **lookup_kwargs)
+ date_list = self.get_date_list(qs)
+
+ if not self.get_make_object_list():
+ # We need this to be a queryset since parent classes introspect it
+ # to find information about the model.
+ qs = qs.none()
+
+ return (date_list, qs, {
+ 'year': date,
+ 'next_year': self.get_next_year(date),
+ 'previous_year': self.get_previous_year(date),
+ })
+
+ def get_make_object_list(self):
+ """
+ Return `True` if this view should contain the full list of objects in
+ the given year.
+ """
+ return self.make_object_list
+
+
+class YearArchiveView(MultipleObjectTemplateResponseMixin, BaseYearArchiveView):
+ """
+ List of objects published in a given year.
+ """
+ template_name_suffix = '_archive_year'
+
+
+class BaseMonthArchiveView(YearMixin, MonthMixin, BaseDateListView):
+ """
+ List of objects published in a given month.
+ """
+ date_list_period = 'day'
+
+ def get_dated_items(self):
+ """
+ Return (date_list, items, extra_context) for this request.
+ """
+ year = self.get_year()
+ month = self.get_month()
+
+ date_field = self.get_date_field()
+ date = _date_from_string(year, self.get_year_format(),
+ month, self.get_month_format())
+
+ since = self._make_date_lookup_arg(date)
+ until = self._make_date_lookup_arg(self._get_next_month(date))
+ lookup_kwargs = {
+ '%s__gte' % date_field: since,
+ '%s__lt' % date_field: until,
+ }
+
+ qs = self.get_dated_queryset(**lookup_kwargs)
+ date_list = self.get_date_list(qs)
+
+ return (date_list, qs, {
+ 'month': date,
+ 'next_month': self.get_next_month(date),
+ 'previous_month': self.get_previous_month(date),
+ })
+
+
+class MonthArchiveView(MultipleObjectTemplateResponseMixin, BaseMonthArchiveView):
+ """
+ List of objects published in a given month.
+ """
+ template_name_suffix = '_archive_month'
+
+
+class BaseWeekArchiveView(YearMixin, WeekMixin, BaseDateListView):
+ """
+ List of objects published in a given week.
+ """
+
+ def get_dated_items(self):
+ """
+ Return (date_list, items, extra_context) for this request.
+ """
+ year = self.get_year()
+ week = self.get_week()
+
+ date_field = self.get_date_field()
+ week_format = self.get_week_format()
+ week_start = {
+ '%W': '1',
+ '%U': '0',
+ }[week_format]
+ date = _date_from_string(year, self.get_year_format(),
+ week_start, '%w',
+ week, week_format)
+
+ since = self._make_date_lookup_arg(date)
+ until = self._make_date_lookup_arg(self._get_next_week(date))
+ lookup_kwargs = {
+ '%s__gte' % date_field: since,
+ '%s__lt' % date_field: until,
+ }
+
+ qs = self.get_dated_queryset(**lookup_kwargs)
+
+ return (None, qs, {
+ 'week': date,
+ 'next_week': self.get_next_week(date),
+ 'previous_week': self.get_previous_week(date),
+ })
+
+
+class WeekArchiveView(MultipleObjectTemplateResponseMixin, BaseWeekArchiveView):
+ """
+ List of objects published in a given week.
+ """
+ template_name_suffix = '_archive_week'
+
+
+class BaseDayArchiveView(YearMixin, MonthMixin, DayMixin, BaseDateListView):
+ """
+ List of objects published on a given day.
+ """
+ def get_dated_items(self):
+ """
+ Return (date_list, items, extra_context) for this request.
+ """
+ year = self.get_year()
+ month = self.get_month()
+ day = self.get_day()
+
+ date = _date_from_string(year, self.get_year_format(),
+ month, self.get_month_format(),
+ day, self.get_day_format())
+
+ return self._get_dated_items(date)
+
+ def _get_dated_items(self, date):
+ """
+ Do the actual heavy lifting of getting the dated items; this accepts a
+ date object so that TodayArchiveView can be trivial.
+ """
+ lookup_kwargs = self._make_single_date_lookup(date)
+ qs = self.get_dated_queryset(**lookup_kwargs)
+
+ return (None, qs, {
+ 'day': date,
+ 'previous_day': self.get_previous_day(date),
+ 'next_day': self.get_next_day(date),
+ 'previous_month': self.get_previous_month(date),
+ 'next_month': self.get_next_month(date)
+ })
+
+
+class DayArchiveView(MultipleObjectTemplateResponseMixin, BaseDayArchiveView):
+ """
+ List of objects published on a given day.
+ """
+ template_name_suffix = "_archive_day"
+
+
+class BaseTodayArchiveView(BaseDayArchiveView):
+ """
+ List of objects published today.
+ """
+
+ def get_dated_items(self):
+ """
+ Return (date_list, items, extra_context) for this request.
+ """
+ return self._get_dated_items(datetime.date.today())
+
+
+class TodayArchiveView(MultipleObjectTemplateResponseMixin, BaseTodayArchiveView):
+ """
+ List of objects published today.
+ """
+ template_name_suffix = "_archive_day"
+
+
+class BaseDateDetailView(YearMixin, MonthMixin, DayMixin, DateMixin, BaseDetailView):
+ """
+ Detail view of a single object on a single date; this differs from the
+ standard DetailView by accepting a year/month/day in the URL.
+ """
+ def get_object(self, queryset=None):
+ """
+ Get the object this request displays.
+ """
+ year = self.get_year()
+ month = self.get_month()
+ day = self.get_day()
+ date = _date_from_string(year, self.get_year_format(),
+ month, self.get_month_format(),
+ day, self.get_day_format())
+
+ # Use a custom queryset if provided
+ qs = queryset or self.get_queryset()
+
+ if not self.get_allow_future() and date > datetime.date.today():
+ raise Http404(_("Future %(verbose_name_plural)s not available because %(class_name)s.allow_future is False.") % {
+ 'verbose_name_plural': qs.model._meta.verbose_name_plural,
+ 'class_name': self.__class__.__name__,
+ })
+
+ # Filter down a queryset from self.queryset using the date from the
+ # URL. This'll get passed as the queryset to DetailView.get_object,
+ # which'll handle the 404
+ lookup_kwargs = self._make_single_date_lookup(date)
+ qs = qs.filter(**lookup_kwargs)
+
+ return super(BaseDetailView, self).get_object(queryset=qs)
+
+
+class DateDetailView(SingleObjectTemplateResponseMixin, BaseDateDetailView):
+ """
+ Detail view of a single object on a single date; this differs from the
+ standard DetailView by accepting a year/month/day in the URL.
+ """
+ template_name_suffix = '_detail'
+
+
+def _date_from_string(year, year_format, month='', month_format='', day='', day_format='', delim='__'):
+ """
+ Helper: get a datetime.date object given a format string and a year,
+ month, and day (only year is mandatory). Raise a 404 for an invalid date.
+ """
+ format = delim.join((year_format, month_format, day_format))
+ datestr = delim.join((year, month, day))
+ try:
+ return datetime.datetime.strptime(force_str(datestr), format).date()
+ except ValueError:
+ raise Http404(_("Invalid date string '%(datestr)s' given format '%(format)s'") % {
+ 'datestr': datestr,
+ 'format': format,
+ })
+
+
+def _get_next_prev(generic_view, date, is_previous, period):
+ """
+ Helper: Get the next or the previous valid date. The idea is to allow
+ links on month/day views to never be 404s by never providing a date
+ that'll be invalid for the given view.
+
+ This is a bit complicated since it handles different intervals of time,
+ hence the coupling to generic_view.
+
+ However in essence the logic comes down to:
+
+ * If allow_empty and allow_future are both true, this is easy: just
+ return the naive result (just the next/previous day/week/month,
+ reguardless of object existence.)
+
+ * If allow_empty is true, allow_future is false, and the naive result
+ isn't in the future, then return it; otherwise return None.
+
+ * If allow_empty is false and allow_future is true, return the next
+ date *that contains a valid object*, even if it's in the future. If
+ there are no next objects, return None.
+
+ * If allow_empty is false and allow_future is false, return the next
+ date that contains a valid object. If that date is in the future, or
+ if there are no next objects, return None.
+
+ """
+ date_field = generic_view.get_date_field()
+ allow_empty = generic_view.get_allow_empty()
+ allow_future = generic_view.get_allow_future()
+
+ get_current = getattr(generic_view, '_get_current_%s' % period)
+ get_next = getattr(generic_view, '_get_next_%s' % period)
+
+ # Bounds of the current interval
+ start, end = get_current(date), get_next(date)
+
+ # If allow_empty is True, the naive result will be valid
+ if allow_empty:
+ if is_previous:
+ result = get_current(start - datetime.timedelta(days=1))
+ else:
+ result = end
+
+ if allow_future or result <= timezone_today():
+ return result
+ else:
+ return None
+
+ # Otherwise, we'll need to go to the database to look for an object
+ # whose date_field is at least (greater than/less than) the given
+ # naive result
+ else:
+ # Construct a lookup and an ordering depending on whether we're doing
+ # a previous date or a next date lookup.
+ if is_previous:
+ lookup = {'%s__lt' % date_field: generic_view._make_date_lookup_arg(start)}
+ ordering = '-%s' % date_field
+ else:
+ lookup = {'%s__gte' % date_field: generic_view._make_date_lookup_arg(end)}
+ ordering = date_field
+
+ # Filter out objects in the future if appropriate.
+ if not allow_future:
+ # Fortunately, to match the implementation of allow_future,
+ # we need __lte, which doesn't conflict with __lt above.
+ if generic_view.uses_datetime_field:
+ now = timezone.now()
+ else:
+ now = timezone_today()
+ lookup['%s__lte' % date_field] = now
+
+ qs = generic_view.get_queryset().filter(**lookup).order_by(ordering)
+
+ # Snag the first object from the queryset; if it doesn't exist that
+ # means there's no next/previous link available.
+ try:
+ result = getattr(qs[0], date_field)
+ except IndexError:
+ return None
+
+ # Convert datetimes to dates in the current time zone.
+ if generic_view.uses_datetime_field:
+ if settings.USE_TZ:
+ result = timezone.localtime(result)
+ result = result.date()
+
+ # Return the first day of the period.
+ return get_current(result)
+
+
+def timezone_today():
+ """
+ Return the current date in the current time zone.
+ """
+ if settings.USE_TZ:
+ return timezone.localtime(timezone.now()).date()
+ else:
+ return datetime.date.today()
diff --git a/lib/python2.7/site-packages/django/views/generic/detail.py b/lib/python2.7/site-packages/django/views/generic/detail.py
new file mode 100644
index 0000000..180da30
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/generic/detail.py
@@ -0,0 +1,173 @@
+from __future__ import unicode_literals
+
+from django.core.exceptions import ImproperlyConfigured, ObjectDoesNotExist
+from django.db import models
+from django.http import Http404
+from django.utils.translation import ugettext as _
+from django.views.generic.base import TemplateResponseMixin, ContextMixin, View
+
+
+class SingleObjectMixin(ContextMixin):
+ """
+ Provides the ability to retrieve a single object for further manipulation.
+ """
+ model = None
+ queryset = None
+ slug_field = 'slug'
+ context_object_name = None
+ slug_url_kwarg = 'slug'
+ pk_url_kwarg = 'pk'
+
+ def get_object(self, queryset=None):
+ """
+ Returns the object the view is displaying.
+
+ By default this requires `self.queryset` and a `pk` or `slug` argument
+ in the URLconf, but subclasses can override this to return any object.
+ """
+ # Use a custom queryset if provided; this is required for subclasses
+ # like DateDetailView
+ if queryset is None:
+ queryset = self.get_queryset()
+
+ # Next, try looking up by primary key.
+ pk = self.kwargs.get(self.pk_url_kwarg, None)
+ slug = self.kwargs.get(self.slug_url_kwarg, None)
+ if pk is not None:
+ queryset = queryset.filter(pk=pk)
+
+ # Next, try looking up by slug.
+ elif slug is not None:
+ slug_field = self.get_slug_field()
+ queryset = queryset.filter(**{slug_field: slug})
+
+ # If none of those are defined, it's an error.
+ else:
+ raise AttributeError("Generic detail view %s must be called with "
+ "either an object pk or a slug."
+ % self.__class__.__name__)
+
+ try:
+ # Get the single item from the filtered queryset
+ obj = queryset.get()
+ except ObjectDoesNotExist:
+ raise Http404(_("No %(verbose_name)s found matching the query") %
+ {'verbose_name': queryset.model._meta.verbose_name})
+ return obj
+
+ def get_queryset(self):
+ """
+ Get the queryset to look an object up against. May not be called if
+ `get_object` is overridden.
+ """
+ if self.queryset is None:
+ if self.model:
+ return self.model._default_manager.all()
+ else:
+ raise ImproperlyConfigured("%(cls)s is missing a queryset. Define "
+ "%(cls)s.model, %(cls)s.queryset, or override "
+ "%(cls)s.get_queryset()." % {
+ 'cls': self.__class__.__name__
+ })
+ return self.queryset._clone()
+
+ def get_slug_field(self):
+ """
+ Get the name of a slug field to be used to look up by slug.
+ """
+ return self.slug_field
+
+ def get_context_object_name(self, obj):
+ """
+ Get the name to use for the object.
+ """
+ if self.context_object_name:
+ return self.context_object_name
+ elif isinstance(obj, models.Model):
+ return obj._meta.model_name
+ else:
+ return None
+
+ def get_context_data(self, **kwargs):
+ """
+ Insert the single object into the context dict.
+ """
+ context = {}
+ if self.object:
+ context['object'] = self.object
+ context_object_name = self.get_context_object_name(self.object)
+ if context_object_name:
+ context[context_object_name] = self.object
+ context.update(kwargs)
+ return super(SingleObjectMixin, self).get_context_data(**context)
+
+
+class BaseDetailView(SingleObjectMixin, View):
+ """
+ A base view for displaying a single object
+ """
+ def get(self, request, *args, **kwargs):
+ self.object = self.get_object()
+ context = self.get_context_data(object=self.object)
+ return self.render_to_response(context)
+
+
+class SingleObjectTemplateResponseMixin(TemplateResponseMixin):
+ template_name_field = None
+ template_name_suffix = '_detail'
+
+ def get_template_names(self):
+ """
+ Return a list of template names to be used for the request. May not be
+ called if render_to_response is overridden. Returns the following list:
+
+ * the value of ``template_name`` on the view (if provided)
+ * the contents of the ``template_name_field`` field on the
+ object instance that the view is operating upon (if available)
+ * ``<app_label>/<model_name><template_name_suffix>.html``
+ """
+ try:
+ names = super(SingleObjectTemplateResponseMixin, self).get_template_names()
+ except ImproperlyConfigured:
+ # If template_name isn't specified, it's not a problem --
+ # we just start with an empty list.
+ names = []
+
+ # If self.template_name_field is set, grab the value of the field
+ # of that name from the object; this is the most specific template
+ # name, if given.
+ if self.object and self.template_name_field:
+ name = getattr(self.object, self.template_name_field, None)
+ if name:
+ names.insert(0, name)
+
+ # The least-specific option is the default <app>/<model>_detail.html;
+ # only use this if the object in question is a model.
+ if isinstance(self.object, models.Model):
+ names.append("%s/%s%s.html" % (
+ self.object._meta.app_label,
+ self.object._meta.model_name,
+ self.template_name_suffix
+ ))
+ elif hasattr(self, 'model') and self.model is not None and issubclass(self.model, models.Model):
+ names.append("%s/%s%s.html" % (
+ self.model._meta.app_label,
+ self.model._meta.model_name,
+ self.template_name_suffix
+ ))
+
+ # If we still haven't managed to find any template names, we should
+ # re-raise the ImproperlyConfigured to alert the user.
+ if not names:
+ raise
+
+ return names
+
+
+class DetailView(SingleObjectTemplateResponseMixin, BaseDetailView):
+ """
+ Render a "detail" view of an object.
+
+ By default this is a model instance looked up from `self.queryset`, but the
+ view will support display of *any* object by overriding `self.get_object()`.
+ """
diff --git a/lib/python2.7/site-packages/django/views/generic/edit.py b/lib/python2.7/site-packages/django/views/generic/edit.py
new file mode 100644
index 0000000..fccacf0
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/generic/edit.py
@@ -0,0 +1,280 @@
+import warnings
+
+from django.forms import models as model_forms
+from django.core.exceptions import ImproperlyConfigured
+from django.http import HttpResponseRedirect
+from django.utils.encoding import force_text
+from django.views.generic.base import TemplateResponseMixin, ContextMixin, View
+from django.views.generic.detail import (SingleObjectMixin,
+ SingleObjectTemplateResponseMixin, BaseDetailView)
+
+
+class FormMixin(ContextMixin):
+ """
+ A mixin that provides a way to show and handle a form in a request.
+ """
+
+ initial = {}
+ form_class = None
+ success_url = None
+ prefix = None
+
+ def get_initial(self):
+ """
+ Returns the initial data to use for forms on this view.
+ """
+ return self.initial.copy()
+
+ def get_prefix(self):
+ """
+ Returns the prefix to use for forms on this view
+ """
+ return self.prefix
+
+ def get_form_class(self):
+ """
+ Returns the form class to use in this view
+ """
+ return self.form_class
+
+ def get_form(self, form_class):
+ """
+ Returns an instance of the form to be used in this view.
+ """
+ return form_class(**self.get_form_kwargs())
+
+ def get_form_kwargs(self):
+ """
+ Returns the keyword arguments for instantiating the form.
+ """
+ kwargs = {
+ 'initial': self.get_initial(),
+ 'prefix': self.get_prefix(),
+ }
+
+ if self.request.method in ('POST', 'PUT'):
+ kwargs.update({
+ 'data': self.request.POST,
+ 'files': self.request.FILES,
+ })
+ return kwargs
+
+ def get_success_url(self):
+ """
+ Returns the supplied success URL.
+ """
+ if self.success_url:
+ # Forcing possible reverse_lazy evaluation
+ url = force_text(self.success_url)
+ else:
+ raise ImproperlyConfigured(
+ "No URL to redirect to. Provide a success_url.")
+ return url
+
+ def form_valid(self, form):
+ """
+ If the form is valid, redirect to the supplied URL.
+ """
+ return HttpResponseRedirect(self.get_success_url())
+
+ def form_invalid(self, form):
+ """
+ If the form is invalid, re-render the context data with the
+ data-filled form and errors.
+ """
+ return self.render_to_response(self.get_context_data(form=form))
+
+
+class ModelFormMixin(FormMixin, SingleObjectMixin):
+ """
+ A mixin that provides a way to show and handle a modelform in a request.
+ """
+ fields = None
+
+ def get_form_class(self):
+ """
+ Returns the form class to use in this view.
+ """
+ if self.form_class:
+ return self.form_class
+ else:
+ if self.model is not None:
+ # If a model has been explicitly provided, use it
+ model = self.model
+ elif hasattr(self, 'object') and self.object is not None:
+ # If this view is operating on a single object, use
+ # the class of that object
+ model = self.object.__class__
+ else:
+ # Try to get a queryset and extract the model class
+ # from that
+ model = self.get_queryset().model
+
+ if self.fields is None:
+ warnings.warn("Using ModelFormMixin (base class of %s) without "
+ "the 'fields' attribute is deprecated." % self.__class__.__name__,
+ PendingDeprecationWarning)
+
+ return model_forms.modelform_factory(model, fields=self.fields)
+
+ def get_form_kwargs(self):
+ """
+ Returns the keyword arguments for instantiating the form.
+ """
+ kwargs = super(ModelFormMixin, self).get_form_kwargs()
+ kwargs.update({'instance': self.object})
+ return kwargs
+
+ def get_success_url(self):
+ """
+ Returns the supplied URL.
+ """
+ if self.success_url:
+ url = self.success_url % self.object.__dict__
+ else:
+ try:
+ url = self.object.get_absolute_url()
+ except AttributeError:
+ raise ImproperlyConfigured(
+ "No URL to redirect to. Either provide a url or define"
+ " a get_absolute_url method on the Model.")
+ return url
+
+ def form_valid(self, form):
+ """
+ If the form is valid, save the associated model.
+ """
+ self.object = form.save()
+ return super(ModelFormMixin, self).form_valid(form)
+
+
+class ProcessFormView(View):
+ """
+ A mixin that renders a form on GET and processes it on POST.
+ """
+ def get(self, request, *args, **kwargs):
+ """
+ Handles GET requests and instantiates a blank version of the form.
+ """
+ form_class = self.get_form_class()
+ form = self.get_form(form_class)
+ return self.render_to_response(self.get_context_data(form=form))
+
+ def post(self, request, *args, **kwargs):
+ """
+ Handles POST requests, instantiating a form instance with the passed
+ POST variables and then checked for validity.
+ """
+ form_class = self.get_form_class()
+ form = self.get_form(form_class)
+ if form.is_valid():
+ return self.form_valid(form)
+ else:
+ return self.form_invalid(form)
+
+ # PUT is a valid HTTP verb for creating (with a known URL) or editing an
+ # object, note that browsers only support POST for now.
+ def put(self, *args, **kwargs):
+ return self.post(*args, **kwargs)
+
+
+class BaseFormView(FormMixin, ProcessFormView):
+ """
+ A base view for displaying a form
+ """
+
+
+class FormView(TemplateResponseMixin, BaseFormView):
+ """
+ A view for displaying a form, and rendering a template response.
+ """
+
+
+class BaseCreateView(ModelFormMixin, ProcessFormView):
+ """
+ Base view for creating an new object instance.
+
+ Using this base class requires subclassing to provide a response mixin.
+ """
+ def get(self, request, *args, **kwargs):
+ self.object = None
+ return super(BaseCreateView, self).get(request, *args, **kwargs)
+
+ def post(self, request, *args, **kwargs):
+ self.object = None
+ return super(BaseCreateView, self).post(request, *args, **kwargs)
+
+
+class CreateView(SingleObjectTemplateResponseMixin, BaseCreateView):
+ """
+ View for creating a new object instance,
+ with a response rendered by template.
+ """
+ template_name_suffix = '_form'
+
+
+class BaseUpdateView(ModelFormMixin, ProcessFormView):
+ """
+ Base view for updating an existing object.
+
+ Using this base class requires subclassing to provide a response mixin.
+ """
+ def get(self, request, *args, **kwargs):
+ self.object = self.get_object()
+ return super(BaseUpdateView, self).get(request, *args, **kwargs)
+
+ def post(self, request, *args, **kwargs):
+ self.object = self.get_object()
+ return super(BaseUpdateView, self).post(request, *args, **kwargs)
+
+
+class UpdateView(SingleObjectTemplateResponseMixin, BaseUpdateView):
+ """
+ View for updating an object,
+ with a response rendered by template.
+ """
+ template_name_suffix = '_form'
+
+
+class DeletionMixin(object):
+ """
+ A mixin providing the ability to delete objects
+ """
+ success_url = None
+
+ def delete(self, request, *args, **kwargs):
+ """
+ Calls the delete() method on the fetched object and then
+ redirects to the success URL.
+ """
+ self.object = self.get_object()
+ success_url = self.get_success_url()
+ self.object.delete()
+ return HttpResponseRedirect(success_url)
+
+ # Add support for browsers which only accept GET and POST for now.
+ def post(self, request, *args, **kwargs):
+ return self.delete(request, *args, **kwargs)
+
+ def get_success_url(self):
+ if self.success_url:
+ return self.success_url % self.object.__dict__
+ else:
+ raise ImproperlyConfigured(
+ "No URL to redirect to. Provide a success_url.")
+
+
+class BaseDeleteView(DeletionMixin, BaseDetailView):
+ """
+ Base view for deleting an object.
+
+ Using this base class requires subclassing to provide a response mixin.
+ """
+
+
+class DeleteView(SingleObjectTemplateResponseMixin, BaseDeleteView):
+ """
+ View for deleting an object retrieved with `self.get_object()`,
+ with a response rendered by template.
+ """
+ template_name_suffix = '_confirm_delete'
diff --git a/lib/python2.7/site-packages/django/views/generic/list.py b/lib/python2.7/site-packages/django/views/generic/list.py
new file mode 100644
index 0000000..1aff345
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/generic/list.py
@@ -0,0 +1,189 @@
+from __future__ import unicode_literals
+
+from django.core.paginator import Paginator, InvalidPage
+from django.core.exceptions import ImproperlyConfigured
+from django.http import Http404
+from django.utils.translation import ugettext as _
+from django.views.generic.base import TemplateResponseMixin, ContextMixin, View
+
+
+class MultipleObjectMixin(ContextMixin):
+ """
+ A mixin for views manipulating multiple objects.
+ """
+ allow_empty = True
+ queryset = None
+ model = None
+ paginate_by = None
+ paginate_orphans = 0
+ context_object_name = None
+ paginator_class = Paginator
+ page_kwarg = 'page'
+
+ def get_queryset(self):
+ """
+ Get the list of items for this view. This must be an iterable, and may
+ be a queryset (in which qs-specific behavior will be enabled).
+ """
+ if self.queryset is not None:
+ queryset = self.queryset
+ if hasattr(queryset, '_clone'):
+ queryset = queryset._clone()
+ elif self.model is not None:
+ queryset = self.model._default_manager.all()
+ else:
+ raise ImproperlyConfigured("'%s' must define 'queryset' or 'model'"
+ % self.__class__.__name__)
+ return queryset
+
+ def paginate_queryset(self, queryset, page_size):
+ """
+ Paginate the queryset, if needed.
+ """
+ paginator = self.get_paginator(
+ queryset, page_size, orphans=self.get_paginate_orphans(),
+ allow_empty_first_page=self.get_allow_empty())
+ page_kwarg = self.page_kwarg
+ page = self.kwargs.get(page_kwarg) or self.request.GET.get(page_kwarg) or 1
+ try:
+ page_number = int(page)
+ except ValueError:
+ if page == 'last':
+ page_number = paginator.num_pages
+ else:
+ raise Http404(_("Page is not 'last', nor can it be converted to an int."))
+ try:
+ page = paginator.page(page_number)
+ return (paginator, page, page.object_list, page.has_other_pages())
+ except InvalidPage as e:
+ raise Http404(_('Invalid page (%(page_number)s): %(message)s') % {
+ 'page_number': page_number,
+ 'message': str(e)
+ })
+
+ def get_paginate_by(self, queryset):
+ """
+ Get the number of items to paginate by, or ``None`` for no pagination.
+ """
+ return self.paginate_by
+
+ def get_paginator(self, queryset, per_page, orphans=0,
+ allow_empty_first_page=True, **kwargs):
+ """
+ Return an instance of the paginator for this view.
+ """
+ return self.paginator_class(
+ queryset, per_page, orphans=orphans,
+ allow_empty_first_page=allow_empty_first_page, **kwargs)
+
+ def get_paginate_orphans(self):
+ """
+ Returns the maximum number of orphans extend the last page by when
+ paginating.
+ """
+ return self.paginate_orphans
+
+ def get_allow_empty(self):
+ """
+ Returns ``True`` if the view should display empty lists, and ``False``
+ if a 404 should be raised instead.
+ """
+ return self.allow_empty
+
+ def get_context_object_name(self, object_list):
+ """
+ Get the name of the item to be used in the context.
+ """
+ if self.context_object_name:
+ return self.context_object_name
+ elif hasattr(object_list, 'model'):
+ return '%s_list' % object_list.model._meta.model_name
+ else:
+ return None
+
+ def get_context_data(self, **kwargs):
+ """
+ Get the context for this view.
+ """
+ queryset = kwargs.pop('object_list', self.object_list)
+ page_size = self.get_paginate_by(queryset)
+ context_object_name = self.get_context_object_name(queryset)
+ if page_size:
+ paginator, page, queryset, is_paginated = self.paginate_queryset(queryset, page_size)
+ context = {
+ 'paginator': paginator,
+ 'page_obj': page,
+ 'is_paginated': is_paginated,
+ 'object_list': queryset
+ }
+ else:
+ context = {
+ 'paginator': None,
+ 'page_obj': None,
+ 'is_paginated': False,
+ 'object_list': queryset
+ }
+ if context_object_name is not None:
+ context[context_object_name] = queryset
+ context.update(kwargs)
+ return super(MultipleObjectMixin, self).get_context_data(**context)
+
+
+class BaseListView(MultipleObjectMixin, View):
+ """
+ A base view for displaying a list of objects.
+ """
+ def get(self, request, *args, **kwargs):
+ self.object_list = self.get_queryset()
+ allow_empty = self.get_allow_empty()
+
+ if not allow_empty:
+ # When pagination is enabled and object_list is a queryset,
+ # it's better to do a cheap query than to load the unpaginated
+ # queryset in memory.
+ if (self.get_paginate_by(self.object_list) is not None
+ and hasattr(self.object_list, 'exists')):
+ is_empty = not self.object_list.exists()
+ else:
+ is_empty = len(self.object_list) == 0
+ if is_empty:
+ raise Http404(_("Empty list and '%(class_name)s.allow_empty' is False.")
+ % {'class_name': self.__class__.__name__})
+ context = self.get_context_data()
+ return self.render_to_response(context)
+
+
+class MultipleObjectTemplateResponseMixin(TemplateResponseMixin):
+ """
+ Mixin for responding with a template and list of objects.
+ """
+ template_name_suffix = '_list'
+
+ def get_template_names(self):
+ """
+ Return a list of template names to be used for the request. Must return
+ a list. May not be called if render_to_response is overridden.
+ """
+ try:
+ names = super(MultipleObjectTemplateResponseMixin, self).get_template_names()
+ except ImproperlyConfigured:
+ # If template_name isn't specified, it's not a problem --
+ # we just start with an empty list.
+ names = []
+
+ # If the list is a queryset, we'll invent a template name based on the
+ # app and model name. This name gets put at the end of the template
+ # name list so that user-supplied names override the automatically-
+ # generated ones.
+ if hasattr(self.object_list, 'model'):
+ opts = self.object_list.model._meta
+ names.append("%s/%s%s.html" % (opts.app_label, opts.model_name, self.template_name_suffix))
+
+ return names
+
+
+class ListView(MultipleObjectTemplateResponseMixin, BaseListView):
+ """
+ Render some list of objects, set by `self.model` or `self.queryset`.
+ `self.queryset` can actually be any iterable of items, not just a queryset.
+ """
diff --git a/lib/python2.7/site-packages/django/views/i18n.py b/lib/python2.7/site-packages/django/views/i18n.py
new file mode 100644
index 0000000..f854447
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/i18n.py
@@ -0,0 +1,305 @@
+import json
+import os
+import gettext as gettext_module
+
+from django import http
+from django.conf import settings
+from django.template import Context, Template
+from django.utils import importlib
+from django.utils.translation import check_for_language, to_locale, get_language
+from django.utils.encoding import smart_text
+from django.utils.formats import get_format_modules, get_format
+from django.utils._os import upath
+from django.utils.http import is_safe_url
+from django.utils import six
+
+def set_language(request):
+ """
+ Redirect to a given url while setting the chosen language in the
+ session or cookie. The url and the language code need to be
+ specified in the request parameters.
+
+ Since this view changes how the user will see the rest of the site, it must
+ only be accessed as a POST request. If called as a GET request, it will
+ redirect to the page in the request (the 'next' parameter) without changing
+ any state.
+ """
+ next = request.REQUEST.get('next')
+ if not is_safe_url(url=next, host=request.get_host()):
+ next = request.META.get('HTTP_REFERER')
+ if not is_safe_url(url=next, host=request.get_host()):
+ next = '/'
+ response = http.HttpResponseRedirect(next)
+ if request.method == 'POST':
+ lang_code = request.POST.get('language', None)
+ if lang_code and check_for_language(lang_code):
+ if hasattr(request, 'session'):
+ request.session['django_language'] = lang_code
+ else:
+ response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code)
+ return response
+
+
+def get_formats():
+ """
+ Returns all formats strings required for i18n to work
+ """
+ FORMAT_SETTINGS = (
+ 'DATE_FORMAT', 'DATETIME_FORMAT', 'TIME_FORMAT',
+ 'YEAR_MONTH_FORMAT', 'MONTH_DAY_FORMAT', 'SHORT_DATE_FORMAT',
+ 'SHORT_DATETIME_FORMAT', 'FIRST_DAY_OF_WEEK', 'DECIMAL_SEPARATOR',
+ 'THOUSAND_SEPARATOR', 'NUMBER_GROUPING',
+ 'DATE_INPUT_FORMATS', 'TIME_INPUT_FORMATS', 'DATETIME_INPUT_FORMATS'
+ )
+ result = {}
+ for module in [settings] + get_format_modules(reverse=True):
+ for attr in FORMAT_SETTINGS:
+ result[attr] = get_format(attr)
+ formats = {}
+ for k, v in result.items():
+ if isinstance(v, (six.string_types, int)):
+ formats[k] = smart_text(v)
+ elif isinstance(v, (tuple, list)):
+ formats[k] = [smart_text(value) for value in v]
+ return formats
+
+
+js_catalog_template = r"""
+{% autoescape off %}
+(function (globals) {
+
+ var django = globals.django || (globals.django = {});
+
+ {% if plural %}
+ django.pluralidx = function (n) {
+ var v={{ plural }};
+ if (typeof(v) == 'boolean') {
+ return v ? 1 : 0;
+ } else {
+ return v;
+ }
+ };
+ {% else %}
+ django.pluralidx = function (count) { return (count == 1) ? 0 : 1; };
+ {% endif %}
+
+ {% if catalog_str %}
+ /* gettext library */
+
+ django.catalog = {{ catalog_str }};
+
+ django.gettext = function (msgid) {
+ var value = django.catalog[msgid];
+ if (typeof(value) == 'undefined') {
+ return msgid;
+ } else {
+ return (typeof(value) == 'string') ? value : value[0];
+ }
+ };
+
+ django.ngettext = function (singular, plural, count) {
+ var value = django.catalog[singular];
+ if (typeof(value) == 'undefined') {
+ return (count == 1) ? singular : plural;
+ } else {
+ return value[django.pluralidx(count)];
+ }
+ };
+
+ django.gettext_noop = function (msgid) { return msgid; };
+
+ django.pgettext = function (context, msgid) {
+ var value = django.gettext(context + '\x04' + msgid);
+ if (value.indexOf('\x04') != -1) {
+ value = msgid;
+ }
+ return value;
+ };
+
+ django.npgettext = function (context, singular, plural, count) {
+ var value = django.ngettext(context + '\x04' + singular, context + '\x04' + plural, count);
+ if (value.indexOf('\x04') != -1) {
+ value = django.ngettext(singular, plural, count);
+ }
+ return value;
+ };
+ {% else %}
+ /* gettext identity library */
+
+ django.gettext = function (msgid) { return msgid; };
+ django.ngettext = function (singular, plural, count) { return (count == 1) ? singular : plural; };
+ django.gettext_noop = function (msgid) { return msgid; };
+ django.pgettext = function (context, msgid) { return msgid; };
+ django.npgettext = function (context, singular, plural, count) { return (count == 1) ? singular : plural; };
+ {% endif %}
+
+ django.interpolate = function (fmt, obj, named) {
+ if (named) {
+ return fmt.replace(/%\(\w+\)s/g, function(match){return String(obj[match.slice(2,-2)])});
+ } else {
+ return fmt.replace(/%s/g, function(match){return String(obj.shift())});
+ }
+ };
+
+
+ /* formatting library */
+
+ django.formats = {{ formats_str }};
+
+ django.get_format = function (format_type) {
+ var value = django.formats[format_type];
+ if (typeof(value) == 'undefined') {
+ return format_type;
+ } else {
+ return value;
+ }
+ };
+
+ /* add to global namespace */
+ globals.pluralidx = django.pluralidx;
+ globals.gettext = django.gettext;
+ globals.ngettext = django.ngettext;
+ globals.gettext_noop = django.gettext_noop;
+ globals.pgettext = django.pgettext;
+ globals.npgettext = django.npgettext;
+ globals.interpolate = django.interpolate;
+ globals.get_format = django.get_format;
+
+}(this));
+{% endautoescape %}
+"""
+
+
+def render_javascript_catalog(catalog=None, plural=None):
+ template = Template(js_catalog_template)
+ indent = lambda s: s.replace('\n', '\n ')
+ context = Context({
+ 'catalog_str': indent(json.dumps(
+ catalog, sort_keys=True, indent=2)) if catalog else None,
+ 'formats_str': indent(json.dumps(
+ get_formats(), sort_keys=True, indent=2)),
+ 'plural': plural,
+ })
+
+ return http.HttpResponse(template.render(context), 'text/javascript')
+
+
+def get_javascript_catalog(locale, domain, packages):
+ default_locale = to_locale(settings.LANGUAGE_CODE)
+ packages = [p for p in packages if p == 'django.conf' or p in settings.INSTALLED_APPS]
+ t = {}
+ paths = []
+ en_selected = locale.startswith('en')
+ en_catalog_missing = True
+ # paths of requested packages
+ for package in packages:
+ p = importlib.import_module(package)
+ path = os.path.join(os.path.dirname(upath(p.__file__)), 'locale')
+ paths.append(path)
+ # add the filesystem paths listed in the LOCALE_PATHS setting
+ paths.extend(list(reversed(settings.LOCALE_PATHS)))
+ # first load all english languages files for defaults
+ for path in paths:
+ try:
+ catalog = gettext_module.translation(domain, path, ['en'])
+ t.update(catalog._catalog)
+ except IOError:
+ pass
+ else:
+ # 'en' is the selected language and at least one of the packages
+ # listed in `packages` has an 'en' catalog
+ if en_selected:
+ en_catalog_missing = False
+ # next load the settings.LANGUAGE_CODE translations if it isn't english
+ if default_locale != 'en':
+ for path in paths:
+ try:
+ catalog = gettext_module.translation(domain, path, [default_locale])
+ except IOError:
+ catalog = None
+ if catalog is not None:
+ t.update(catalog._catalog)
+ # last load the currently selected language, if it isn't identical to the default.
+ if locale != default_locale:
+ # If the currently selected language is English but it doesn't have a
+ # translation catalog (presumably due to being the language translated
+ # from) then a wrong language catalog might have been loaded in the
+ # previous step. It needs to be discarded.
+ if en_selected and en_catalog_missing:
+ t = {}
+ else:
+ locale_t = {}
+ for path in paths:
+ try:
+ catalog = gettext_module.translation(domain, path, [locale])
+ except IOError:
+ catalog = None
+ if catalog is not None:
+ locale_t.update(catalog._catalog)
+ if locale_t:
+ t = locale_t
+ plural = None
+ if '' in t:
+ for l in t[''].split('\n'):
+ if l.startswith('Plural-Forms:'):
+ plural = l.split(':', 1)[1].strip()
+ if plural is not None:
+ # this should actually be a compiled function of a typical plural-form:
+ # Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;
+ plural = [el.strip() for el in plural.split(';') if el.strip().startswith('plural=')][0].split('=', 1)[1]
+
+ pdict = {}
+ maxcnts = {}
+ catalog = {}
+ for k, v in t.items():
+ if k == '':
+ continue
+ if isinstance(k, six.string_types):
+ catalog[k] = v
+ elif isinstance(k, tuple):
+ msgid = k[0]
+ cnt = k[1]
+ maxcnts[msgid] = max(cnt, maxcnts.get(msgid, 0))
+ pdict.setdefault(msgid, {})[cnt] = v
+ else:
+ raise TypeError(k)
+ for k, v in pdict.items():
+ catalog[k] = [v.get(i, '') for i in range(maxcnts[msgid] + 1)]
+
+ return catalog, plural
+
+
+def null_javascript_catalog(request, domain=None, packages=None):
+ """
+ Returns "identity" versions of the JavaScript i18n functions -- i.e.,
+ versions that don't actually do anything.
+ """
+ return render_javascript_catalog()
+
+
+def javascript_catalog(request, domain='djangojs', packages=None):
+ """
+ Returns the selected language catalog as a javascript library.
+
+ Receives the list of packages to check for translations in the
+ packages parameter either from an infodict or as a +-delimited
+ string from the request. Default is 'django.conf'.
+
+ Additionally you can override the gettext domain for this view,
+ but usually you don't want to do that, as JavaScript messages
+ go to the djangojs domain. But this might be needed if you
+ deliver your JavaScript source from Django templates.
+ """
+ locale = to_locale(get_language())
+
+ if request.GET and 'language' in request.GET:
+ if check_for_language(request.GET['language']):
+ locale = to_locale(request.GET['language'])
+
+ if packages is None:
+ packages = ['django.conf']
+ if isinstance(packages, six.string_types):
+ packages = packages.split('+')
+
+ catalog, plural = get_javascript_catalog(locale, domain, packages)
+ return render_javascript_catalog(catalog, plural)
diff --git a/lib/python2.7/site-packages/django/views/static.py b/lib/python2.7/site-packages/django/views/static.py
new file mode 100644
index 0000000..c1baacd
--- /dev/null
+++ b/lib/python2.7/site-packages/django/views/static.py
@@ -0,0 +1,143 @@
+"""
+Views and functions for serving static files. These are only to be used
+during development, and SHOULD NOT be used in a production setting.
+"""
+from __future__ import unicode_literals
+
+import mimetypes
+import os
+import stat
+import posixpath
+import re
+
+from django.http import (CompatibleStreamingHttpResponse, Http404,
+ HttpResponse, HttpResponseRedirect, HttpResponseNotModified)
+from django.template import loader, Template, Context, TemplateDoesNotExist
+from django.utils.http import http_date, parse_http_date
+from django.utils.six.moves.urllib.parse import unquote
+from django.utils.translation import ugettext as _, ugettext_noop
+
+def serve(request, path, document_root=None, show_indexes=False):
+ """
+ Serve static files below a given point in the directory structure.
+
+ To use, put a URL pattern such as::
+
+ (r'^(?P<path>.*)$', 'django.views.static.serve', {'document_root' : '/path/to/my/files/'})
+
+ in your URLconf. You must provide the ``document_root`` param. You may
+ also set ``show_indexes`` to ``True`` if you'd like to serve a basic index
+ of the directory. This index view will use the template hardcoded below,
+ but if you'd like to override it, you can create a template called
+ ``static/directory_index.html``.
+ """
+ path = posixpath.normpath(unquote(path))
+ path = path.lstrip('/')
+ newpath = ''
+ for part in path.split('/'):
+ if not part:
+ # Strip empty path components.
+ continue
+ drive, part = os.path.splitdrive(part)
+ head, part = os.path.split(part)
+ if part in (os.curdir, os.pardir):
+ # Strip '.' and '..' in path.
+ continue
+ newpath = os.path.join(newpath, part).replace('\\', '/')
+ if newpath and path != newpath:
+ return HttpResponseRedirect(newpath)
+ fullpath = os.path.join(document_root, newpath)
+ if os.path.isdir(fullpath):
+ if show_indexes:
+ return directory_index(newpath, fullpath)
+ raise Http404(_("Directory indexes are not allowed here."))
+ if not os.path.exists(fullpath):
+ raise Http404(_('"%(path)s" does not exist') % {'path': fullpath})
+ # Respect the If-Modified-Since header.
+ statobj = os.stat(fullpath)
+ if not was_modified_since(request.META.get('HTTP_IF_MODIFIED_SINCE'),
+ statobj.st_mtime, statobj.st_size):
+ return HttpResponseNotModified()
+ content_type, encoding = mimetypes.guess_type(fullpath)
+ content_type = content_type or 'application/octet-stream'
+ response = CompatibleStreamingHttpResponse(open(fullpath, 'rb'),
+ content_type=content_type)
+ response["Last-Modified"] = http_date(statobj.st_mtime)
+ if stat.S_ISREG(statobj.st_mode):
+ response["Content-Length"] = statobj.st_size
+ if encoding:
+ response["Content-Encoding"] = encoding
+ return response
+
+
+DEFAULT_DIRECTORY_INDEX_TEMPLATE = """
+{% load i18n %}
+<!DOCTYPE html>
+<html lang="en">
+ <head>
+ <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+ <meta http-equiv="Content-Language" content="en-us" />
+ <meta name="robots" content="NONE,NOARCHIVE" />
+ <title>{% blocktrans %}Index of {{ directory }}{% endblocktrans %}</title>
+ </head>
+ <body>
+ <h1>{% blocktrans %}Index of {{ directory }}{% endblocktrans %}</h1>
+ <ul>
+ {% ifnotequal directory "/" %}
+ <li><a href="../">../</a></li>
+ {% endifnotequal %}
+ {% for f in file_list %}
+ <li><a href="{{ f|urlencode }}">{{ f }}</a></li>
+ {% endfor %}
+ </ul>
+ </body>
+</html>
+"""
+template_translatable = ugettext_noop("Index of %(directory)s")
+
+def directory_index(path, fullpath):
+ try:
+ t = loader.select_template(['static/directory_index.html',
+ 'static/directory_index'])
+ except TemplateDoesNotExist:
+ t = Template(DEFAULT_DIRECTORY_INDEX_TEMPLATE, name='Default directory index template')
+ files = []
+ for f in os.listdir(fullpath):
+ if not f.startswith('.'):
+ if os.path.isdir(os.path.join(fullpath, f)):
+ f += '/'
+ files.append(f)
+ c = Context({
+ 'directory' : path + '/',
+ 'file_list' : files,
+ })
+ return HttpResponse(t.render(c))
+
+def was_modified_since(header=None, mtime=0, size=0):
+ """
+ Was something modified since the user last downloaded it?
+
+ header
+ This is the value of the If-Modified-Since header. If this is None,
+ I'll just return True.
+
+ mtime
+ This is the modification time of the item we're talking about.
+
+ size
+ This is the size of the item we're talking about.
+ """
+ try:
+ if header is None:
+ raise ValueError
+ matches = re.match(r"^([^;]+)(; length=([0-9]+))?$", header,
+ re.IGNORECASE)
+ header_mtime = parse_http_date(matches.group(1))
+ header_len = matches.group(3)
+ if header_len and int(header_len) != size:
+ raise ValueError
+ if int(mtime) > header_mtime:
+ raise ValueError
+ except (AttributeError, ValueError, OverflowError):
+ return True
+ return False