Loading django/template/loader_tags.py +14 −2 Original line number Diff line number Diff line Loading @@ -171,6 +171,8 @@ class ExtendsNode(Node): class IncludeNode(Node): context_key = '__include_context' def __init__(self, template, *args, **kwargs): self.template = template self.extra_context = kwargs.pop('extra_context', {}) Loading @@ -178,12 +180,22 @@ class IncludeNode(Node): super(IncludeNode, self).__init__(*args, **kwargs) def render(self, context): """ Render the specified template and context. Cache the template object in render_context to avoid reparsing and loading when used in a for loop. """ try: template = self.template.resolve(context) # Does this quack like a Template? if not callable(getattr(template, 'render', None)): # If not, we'll try get_template template = context.template.engine.get_template(template) # If not, we'll try our cache, and get_template() template_name = template cache = context.render_context.setdefault(self.context_key, {}) template = cache.get(template_name) if template is None: template = context.template.engine.get_template(template_name) cache[template_name] = template values = { name: var.resolve(context) for name, var in six.iteritems(self.extra_context) Loading docs/releases/1.9.txt +3 −0 Original line number Diff line number Diff line Loading @@ -314,6 +314,9 @@ Templates * The ``timesince`` and ``timeuntil`` filters were improved to deal with leap years when given large time spans. * The ``include`` tag now caches parsed templates objects during template rendering, speeding up reuse in places such as for loops. Requests and Responses ^^^^^^^^^^^^^^^^^^^^^^ Loading tests/template_tests/syntax_tests/test_if_changed.py +14 −0 Original line number Diff line number Diff line Loading @@ -196,3 +196,17 @@ class IfChangedTests(SimpleTestCase): template = self.engine.from_string('{% ifchanged %}{% cycle "1st time" "2nd time" %}{% endifchanged %}') output = template.render(Context({})) self.assertEqual(output, '1st time') def test_include(self): """ #23516 -- This works as a regression test only if the cached loader isn't used. Hence we don't use the @setup decorator. """ engine = Engine(loaders=[ ('django.template.loaders.locmem.Loader', { 'template': '{% for x in vars %}{% include "include" %}{% endfor %}', 'include': '{% ifchanged %}{{ x }}{% endifchanged %}', }), ]) output = engine.render_to_string('template', dict(vars=[1, 1, 2, 2, 3, 3])) self.assertEqual(output, "123") Loading
django/template/loader_tags.py +14 −2 Original line number Diff line number Diff line Loading @@ -171,6 +171,8 @@ class ExtendsNode(Node): class IncludeNode(Node): context_key = '__include_context' def __init__(self, template, *args, **kwargs): self.template = template self.extra_context = kwargs.pop('extra_context', {}) Loading @@ -178,12 +180,22 @@ class IncludeNode(Node): super(IncludeNode, self).__init__(*args, **kwargs) def render(self, context): """ Render the specified template and context. Cache the template object in render_context to avoid reparsing and loading when used in a for loop. """ try: template = self.template.resolve(context) # Does this quack like a Template? if not callable(getattr(template, 'render', None)): # If not, we'll try get_template template = context.template.engine.get_template(template) # If not, we'll try our cache, and get_template() template_name = template cache = context.render_context.setdefault(self.context_key, {}) template = cache.get(template_name) if template is None: template = context.template.engine.get_template(template_name) cache[template_name] = template values = { name: var.resolve(context) for name, var in six.iteritems(self.extra_context) Loading
docs/releases/1.9.txt +3 −0 Original line number Diff line number Diff line Loading @@ -314,6 +314,9 @@ Templates * The ``timesince`` and ``timeuntil`` filters were improved to deal with leap years when given large time spans. * The ``include`` tag now caches parsed templates objects during template rendering, speeding up reuse in places such as for loops. Requests and Responses ^^^^^^^^^^^^^^^^^^^^^^ Loading
tests/template_tests/syntax_tests/test_if_changed.py +14 −0 Original line number Diff line number Diff line Loading @@ -196,3 +196,17 @@ class IfChangedTests(SimpleTestCase): template = self.engine.from_string('{% ifchanged %}{% cycle "1st time" "2nd time" %}{% endifchanged %}') output = template.render(Context({})) self.assertEqual(output, '1st time') def test_include(self): """ #23516 -- This works as a regression test only if the cached loader isn't used. Hence we don't use the @setup decorator. """ engine = Engine(loaders=[ ('django.template.loaders.locmem.Loader', { 'template': '{% for x in vars %}{% include "include" %}{% endfor %}', 'include': '{% ifchanged %}{{ x }}{% endifchanged %}', }), ]) output = engine.render_to_string('template', dict(vars=[1, 1, 2, 2, 3, 3])) self.assertEqual(output, "123")