diff --git a/django/template/loader_tags.py b/django/template/loader_tags.py index 7451e0b1bff..b63938abb07 100644 --- a/django/template/loader_tags.py +++ b/django/template/loader_tags.py @@ -1,5 +1,6 @@ from django.conf import settings -from django.template.base import TemplateSyntaxError, Library, Node, TextNode, token_kwargs +from django.template.base import TemplateSyntaxError, Library, Node, TextNode,\ + token_kwargs, Variable from django.template.loader import get_template from django.utils.safestring import mark_safe @@ -74,26 +75,23 @@ class BlockNode(Node): class ExtendsNode(Node): must_be_first = True - def __init__(self, nodelist, parent_name, parent_name_expr, template_dirs=None): + def __init__(self, nodelist, parent_name, template_dirs=None): self.nodelist = nodelist - self.parent_name, self.parent_name_expr = parent_name, parent_name_expr + self.parent_name = parent_name self.template_dirs = template_dirs self.blocks = dict([(n.name, n) for n in nodelist.get_nodes_by_type(BlockNode)]) def __repr__(self): - if self.parent_name_expr: - return "" % self.parent_name_expr.token - return '' % self.parent_name + return '' % self.parent_name.token def get_parent(self, context): - if self.parent_name_expr: - parent = self.parent_name_expr.resolve(context) - else: - parent = self.parent_name + parent = self.parent_name.resolve(context) if not parent: error_msg = "Invalid template name in 'extends' tag: %r." % parent - if self.parent_name_expr: - error_msg += " Got this from the '%s' variable." % self.parent_name_expr.token + if self.parent_name.filters or\ + isinstance(self.parent_name.var, Variable): + 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 @@ -212,15 +210,11 @@ def do_extends(parser, token): bits = token.split_contents() if len(bits) != 2: raise TemplateSyntaxError("'%s' takes one argument" % bits[0]) - parent_name, parent_name_expr = None, None - if bits[1][0] in ('"', "'") and bits[1][-1] == bits[1][0]: - parent_name = bits[1][1:-1] - else: - parent_name_expr = parser.compile_filter(bits[1]) + parent_name = parser.compile_filter(bits[1]) nodelist = parser.parse() if nodelist.get_nodes_by_type(ExtendsNode): raise TemplateSyntaxError("'%s' cannot appear more than once in the same template" % bits[0]) - return ExtendsNode(nodelist, parent_name, parent_name_expr) + return ExtendsNode(nodelist, parent_name) @register.tag('include') def do_include(parser, token): diff --git a/docs/releases/1.4.txt b/docs/releases/1.4.txt index 2014a1004da..7b45f9e4e20 100644 --- a/docs/releases/1.4.txt +++ b/docs/releases/1.4.txt @@ -1031,6 +1031,17 @@ If you depended on the output of this command -- if you parsed it, for example management commands in a script, use :djadmin:`manage.py help --commands ` instead. +``extends`` template tag +~~~~~~~~~~~~~~~~~~~~~~~~ + +Previously, the :ttag:`extends` tag used a buggy method of parsing arguments, +which could lead to it erroneously considering an argument as a string literal +when it wasn't. It now utilises ``parser.compile_filter`` like other tags. + +The internals of the tag aren't part of the official stable API, but in the +interests of full disclosure, the ``ExtendsNode.__init__`` definition has +changed which may break any custom tags that use this node class. + Features deprecated in 1.4 ========================== diff --git a/tests/regressiontests/templates/tests.py b/tests/regressiontests/templates/tests.py index 631c58c3a3d..d5de05ca09e 100644 --- a/tests/regressiontests/templates/tests.py +++ b/tests/regressiontests/templates/tests.py @@ -1204,6 +1204,9 @@ class Templates(unittest.TestCase): 'inheritance40': ("{% extends 'inheritance33' %}{% block opt %}new{{ block.super }}{% endblock %}", {'optional': 1}, '1new23'), 'inheritance41': ("{% extends 'inheritance36' %}{% block opt %}new{{ block.super }}{% endblock %}", {'numbers': '123'}, '_new1_new2_new3_'), + # Expression starting and ending with a quote + 'inheritance42': ("{% extends 'inheritance02'|cut:' ' %}", {}, '1234'), + ### LOADING TAG LIBRARIES ################################################# 'load01': ("{% load testtags subpackage.echo %}{% echo test %} {% echo2 \"test\" %}", {}, "test test"), 'load02': ("{% load subpackage.echo %}{% echo2 \"test\" %}", {}, "test"),