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