| 1 |
from django.conf import settings |
|---|
| 2 |
from django.core.exceptions import ImproperlyConfigured |
|---|
| 3 |
|
|---|
| 4 |
_standard_context_processors = None |
|---|
| 5 |
|
|---|
| 6 |
class ContextPopException(Exception): |
|---|
| 7 |
"pop() has been called more times than push()" |
|---|
| 8 |
pass |
|---|
| 9 |
|
|---|
| 10 |
class Context(object): |
|---|
| 11 |
"A stack container for variable context" |
|---|
| 12 |
def __init__(self, dict_=None, autoescape=True): |
|---|
| 13 |
dict_ = dict_ or {} |
|---|
| 14 |
self.dicts = [dict_] |
|---|
| 15 |
self.autoescape = autoescape |
|---|
| 16 |
|
|---|
| 17 |
def __repr__(self): |
|---|
| 18 |
return repr(self.dicts) |
|---|
| 19 |
|
|---|
| 20 |
def __iter__(self): |
|---|
| 21 |
for d in self.dicts: |
|---|
| 22 |
yield d |
|---|
| 23 |
|
|---|
| 24 |
def push(self): |
|---|
| 25 |
d = {} |
|---|
| 26 |
self.dicts = [d] + self.dicts |
|---|
| 27 |
return d |
|---|
| 28 |
|
|---|
| 29 |
def pop(self): |
|---|
| 30 |
if len(self.dicts) == 1: |
|---|
| 31 |
raise ContextPopException |
|---|
| 32 |
return self.dicts.pop(0) |
|---|
| 33 |
|
|---|
| 34 |
def __setitem__(self, key, value): |
|---|
| 35 |
"Set a variable in the current context" |
|---|
| 36 |
self.dicts[0][key] = value |
|---|
| 37 |
|
|---|
| 38 |
def __getitem__(self, key): |
|---|
| 39 |
"Get a variable's value, starting at the current context and going upward" |
|---|
| 40 |
for d in self.dicts: |
|---|
| 41 |
if key in d: |
|---|
| 42 |
return d[key] |
|---|
| 43 |
raise KeyError(key) |
|---|
| 44 |
|
|---|
| 45 |
def __delitem__(self, key): |
|---|
| 46 |
"Delete a variable from the current context" |
|---|
| 47 |
del self.dicts[0][key] |
|---|
| 48 |
|
|---|
| 49 |
def has_key(self, key): |
|---|
| 50 |
for d in self.dicts: |
|---|
| 51 |
if key in d: |
|---|
| 52 |
return True |
|---|
| 53 |
return False |
|---|
| 54 |
|
|---|
| 55 |
__contains__ = has_key |
|---|
| 56 |
|
|---|
| 57 |
def get(self, key, otherwise=None): |
|---|
| 58 |
for d in self.dicts: |
|---|
| 59 |
if key in d: |
|---|
| 60 |
return d[key] |
|---|
| 61 |
return otherwise |
|---|
| 62 |
|
|---|
| 63 |
def update(self, other_dict): |
|---|
| 64 |
"Like dict.update(). Pushes an entire dictionary's keys and values onto the context." |
|---|
| 65 |
self.dicts = [other_dict] + self.dicts |
|---|
| 66 |
return other_dict |
|---|
| 67 |
|
|---|
| 68 |
# This is a function rather than module-level procedural code because we only |
|---|
| 69 |
# want it to execute if somebody uses RequestContext. |
|---|
| 70 |
def get_standard_processors(): |
|---|
| 71 |
global _standard_context_processors |
|---|
| 72 |
if _standard_context_processors is None: |
|---|
| 73 |
processors = [] |
|---|
| 74 |
for path in settings.TEMPLATE_CONTEXT_PROCESSORS: |
|---|
| 75 |
i = path.rfind('.') |
|---|
| 76 |
module, attr = path[:i], path[i+1:] |
|---|
| 77 |
try: |
|---|
| 78 |
mod = __import__(module, {}, {}, [attr]) |
|---|
| 79 |
except ImportError, e: |
|---|
| 80 |
raise ImproperlyConfigured('Error importing request processor module %s: "%s"' % (module, e)) |
|---|
| 81 |
try: |
|---|
| 82 |
func = getattr(mod, attr) |
|---|
| 83 |
except AttributeError: |
|---|
| 84 |
raise ImproperlyConfigured('Module "%s" does not define a "%s" callable request processor' % (module, attr)) |
|---|
| 85 |
processors.append(func) |
|---|
| 86 |
_standard_context_processors = tuple(processors) |
|---|
| 87 |
return _standard_context_processors |
|---|
| 88 |
|
|---|
| 89 |
class RequestContext(Context): |
|---|
| 90 |
""" |
|---|
| 91 |
This subclass of template.Context automatically populates itself using |
|---|
| 92 |
the processors defined in TEMPLATE_CONTEXT_PROCESSORS. |
|---|
| 93 |
Additional processors can be specified as a list of callables |
|---|
| 94 |
using the "processors" keyword argument. |
|---|
| 95 |
""" |
|---|
| 96 |
def __init__(self, request, dict=None, processors=None): |
|---|
| 97 |
Context.__init__(self, dict) |
|---|
| 98 |
if processors is None: |
|---|
| 99 |
processors = () |
|---|
| 100 |
else: |
|---|
| 101 |
processors = tuple(processors) |
|---|
| 102 |
for processor in get_standard_processors() + processors: |
|---|
| 103 |
self.update(processor(request)) |
|---|