From 0f3eb8260b251a15c57f577fb33baad88b284942 Mon Sep 17 00:00:00 2001 From: Aymeric Augustin Date: Sat, 14 Feb 2015 10:21:06 +0100 Subject: [PATCH] [1.8.x] Fixed #24338 -- Accepted Template wrapper in {% extends %}. Explicitly checking for django.template.Template subclasses is preferrable to duck-typing because both the django.template.Template and django.template.backends.django.Template have a render() method. Thanks spectras for the report. Backport of 47ee7b48 from master --- django/template/loader_tags.py | 11 ++++++++--- tests/template_tests/tests.py | 12 +++++++++++- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/django/template/loader_tags.py b/django/template/loader_tags.py index f1c08ee955..e6635258a7 100644 --- a/django/template/loader_tags.py +++ b/django/template/loader_tags.py @@ -1,7 +1,8 @@ from collections import defaultdict from django.template.base import ( - Library, Node, TemplateSyntaxError, TextNode, Variable, token_kwargs, + Library, Node, Template, TemplateSyntaxError, TextNode, Variable, + token_kwargs, ) from django.utils import six from django.utils.safestring import mark_safe @@ -100,8 +101,12 @@ class ExtendsNode(Node): error_msg += " Got this from the '%s' variable." %\ self.parent_name.token raise TemplateSyntaxError(error_msg) - if hasattr(parent, 'render'): - return parent # parent is a Template object + if isinstance(parent, Template): + # parent is a django.template.Template + return parent + if isinstance(getattr(parent, 'template', None), Template): + # parent is a django.template.backends.django.Template + return parent.template return context.engine.get_template(parent) def render(self, context): diff --git a/tests/template_tests/tests.py b/tests/template_tests/tests.py index c57c3d1479..ffc3064b41 100644 --- a/tests/template_tests/tests.py +++ b/tests/template_tests/tests.py @@ -10,7 +10,7 @@ from django.contrib.auth.models import Group from django.core import urlresolvers from django.template import ( Context, RequestContext, Template, TemplateSyntaxError, - base as template_base, loader, + base as template_base, engines, loader, ) from django.template.engine import Engine from django.template.loaders import app_directories, filesystem @@ -414,6 +414,16 @@ class TemplateRegressionTests(SimpleTestCase): t1 = Template('{% debug %}') self.assertIn("清風", t1.render(c1)) + def test_extends_generic_template(self): + """ + {% extends %} accepts django.template.backends.django.Template (#24338). + """ + parent = engines['django'].from_string( + '{% block content %}parent{% endblock %}') + child = engines['django'].from_string( + '{% extends parent %}{% block content %}child{% endblock %}') + self.assertEqual(child.render({'parent': parent}), 'child') + class TemplateTagLoading(SimpleTestCase):