summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAymeric Augustin <aymeric.augustin@m4x.org>2015-02-19 23:20:27 +0100
committerAymeric Augustin <aymeric.augustin@m4x.org>2015-02-20 22:28:24 +0100
commite4e140c49b1bd3dc8ae11900a0089ec908483cf0 (patch)
tree7cdaf69e99ea9cb63daf9543b1df1bbbeea587f5
parent88e6fbb2e341657cb5365b9b78fb44e3c7065d2d (diff)
[1.8.x] Removed a non-obvious side-effect of assigning Context.template.
Explicit is better than implicit. Backport of 51b606f from master
-rw-r--r--django/template/base.py14
-rw-r--r--django/template/context.py55
2 files changed, 37 insertions, 32 deletions
diff --git a/django/template/base.py b/django/template/base.py
index 76f77fc793..0c57050313 100644
--- a/django/template/base.py
+++ b/django/template/base.py
@@ -202,19 +202,15 @@ class Template(object):
def render(self, context):
"Display stage -- can be called many times"
- # Set context.template to the original template -- as opposed to
- # extended or included templates -- during rendering. This may be
- # used for accessing context.template.engine.
- toplevel_render = context.template is None
- if toplevel_render:
- context.template = self
context.render_context.push()
try:
- return self._render(context)
+ if context.template is None:
+ with context.bind_template(self):
+ return self._render(context)
+ else:
+ return self._render(context)
finally:
context.render_context.pop()
- if toplevel_render:
- context.template = None
class Token(object):
diff --git a/django/template/context.py b/django/template/context.py
index b4983d1909..af4fb8853b 100644
--- a/django/template/context.py
+++ b/django/template/context.py
@@ -1,4 +1,5 @@
import warnings
+from contextlib import contextmanager
from copy import copy
from django.utils.deprecation import RemovedInDjango20Warning
@@ -134,8 +135,8 @@ class Context(BaseContext):
self.use_l10n = use_l10n
self.use_tz = use_tz
self.render_context = RenderContext()
- # Set to the original template during rendering -- as opposed to
- # extended or included templates
+ # Set to the original template -- as opposed to extended or included
+ # templates -- during rendering, see bind_template.
self.template = None
super(Context, self).__init__(dict_)
@@ -143,6 +144,16 @@ class Context(BaseContext):
def current_app(self):
return None if self._current_app is _current_app_undefined else self._current_app
+ @contextmanager
+ def bind_template(self, template):
+ if self.template is not None:
+ raise RuntimeError("Context is already bound to a template")
+ self.template = template
+ try:
+ yield
+ finally:
+ self.template = None
+
def __copy__(self):
duplicate = super(Context, self).__copy__()
duplicate.render_context = copy(self.render_context)
@@ -210,28 +221,26 @@ class RequestContext(Context):
self._processors_index = len(self.dicts)
self.update({}) # placeholder for context processors output
- @property
- def template(self):
- return self._template
+ @contextmanager
+ def bind_template(self, template):
+ if self.template is not None:
+ raise RuntimeError("Context is already bound to a template")
+
+ self.template = template
+ # Set context processors according to the template engine's settings.
+ processors = (template.engine.template_context_processors +
+ self._processors)
+ updates = {}
+ for processor in processors:
+ updates.update(processor(self.request))
+ self.dicts[self._processors_index] = updates
- @template.setter
- def template(self, template):
- # Execute context processors when Template.render(self, context) sets
- # context.template = self. Until then, since the context isn't tied to
- # an engine, it has no way to know which context processors to apply.
- self._template = template
- if hasattr(self, '_processors_index'):
- if template is None:
- # Unset context processors.
- self.dicts[self._processors_index] = {}
- else:
- # Set context processors for this engine.
- processors = (template.engine.template_context_processors +
- self._processors)
- updates = {}
- for processor in processors:
- updates.update(processor(self.request))
- self.dicts[self._processors_index] = updates
+ try:
+ yield
+ finally:
+ self.template = None
+ # Unset context processors.
+ self.dicts[self._processors_index] = {}
def new(self, values=None):
new_context = super(RequestContext, self).new(values)