Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Fixed #17660 -- Standardize extends tag token parsing

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17568 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit 0e54c23caf21e5680aff68660b5d5b5937b98262 1 parent 7d7d2d3
Chris Beaven authored February 21, 2012
30  django/template/loader_tags.py
... ...
@@ -1,5 +1,6 @@
1 1
 from django.conf import settings
2  
-from django.template.base import TemplateSyntaxError, Library, Node, TextNode, token_kwargs
  2
+from django.template.base import TemplateSyntaxError, Library, Node, TextNode,\
  3
+    token_kwargs, Variable
3 4
 from django.template.loader import get_template
4 5
 from django.utils.safestring import mark_safe
5 6
 
@@ -74,26 +75,23 @@ def super(self):
74 75
 class ExtendsNode(Node):
75 76
     must_be_first = True
76 77
 
77  
-    def __init__(self, nodelist, parent_name, parent_name_expr, template_dirs=None):
  78
+    def __init__(self, nodelist, parent_name, template_dirs=None):
78 79
         self.nodelist = nodelist
79  
-        self.parent_name, self.parent_name_expr = parent_name, parent_name_expr
  80
+        self.parent_name = parent_name
80 81
         self.template_dirs = template_dirs
81 82
         self.blocks = dict([(n.name, n) for n in nodelist.get_nodes_by_type(BlockNode)])
82 83
 
83 84
     def __repr__(self):
84  
-        if self.parent_name_expr:
85  
-            return "<ExtendsNode: extends %s>" % self.parent_name_expr.token
86  
-        return '<ExtendsNode: extends "%s">' % self.parent_name
  85
+        return '<ExtendsNode: extends %s>' % self.parent_name.token
87 86
 
88 87
     def get_parent(self, context):
89  
-        if self.parent_name_expr:
90  
-            parent = self.parent_name_expr.resolve(context)
91  
-        else:
92  
-            parent = self.parent_name
  88
+        parent = self.parent_name.resolve(context)
93 89
         if not parent:
94 90
             error_msg = "Invalid template name in 'extends' tag: %r." % parent
95  
-            if self.parent_name_expr:
96  
-                error_msg += " Got this from the '%s' variable." % self.parent_name_expr.token
  91
+            if self.parent_name.filters or\
  92
+                    isinstance(self.parent_name.var, Variable):
  93
+                error_msg += " Got this from the '%s' variable." %\
  94
+                    self.parent_name.token
97 95
             raise TemplateSyntaxError(error_msg)
98 96
         if hasattr(parent, 'render'):
99 97
             return parent # parent is a Template object
@@ -212,15 +210,11 @@ def do_extends(parser, token):
212 210
     bits = token.split_contents()
213 211
     if len(bits) != 2:
214 212
         raise TemplateSyntaxError("'%s' takes one argument" % bits[0])
215  
-    parent_name, parent_name_expr = None, None
216  
-    if bits[1][0] in ('"', "'") and bits[1][-1] == bits[1][0]:
217  
-        parent_name = bits[1][1:-1]
218  
-    else:
219  
-        parent_name_expr = parser.compile_filter(bits[1])
  213
+    parent_name = parser.compile_filter(bits[1])
220 214
     nodelist = parser.parse()
221 215
     if nodelist.get_nodes_by_type(ExtendsNode):
222 216
         raise TemplateSyntaxError("'%s' cannot appear more than once in the same template" % bits[0])
223  
-    return ExtendsNode(nodelist, parent_name, parent_name_expr)
  217
+    return ExtendsNode(nodelist, parent_name)
224 218
 
225 219
 @register.tag('include')
226 220
 def do_include(parser, token):
11  docs/releases/1.4.txt
@@ -1031,6 +1031,17 @@ If you depended on the output of this command -- if you parsed it, for example
1031 1031
 management commands in a script, use
1032 1032
 :djadmin:`manage.py help --commands <help>` instead.
1033 1033
 
  1034
+``extends`` template tag
  1035
+~~~~~~~~~~~~~~~~~~~~~~~~
  1036
+
  1037
+Previously, the :ttag:`extends` tag used a buggy method of parsing arguments,
  1038
+which could lead to it erroneously considering an argument as a string literal
  1039
+when it wasn't.  It now utilises ``parser.compile_filter`` like other tags.
  1040
+
  1041
+The internals of the tag aren't part of the official stable API, but in the
  1042
+interests of full disclosure, the ``ExtendsNode.__init__`` definition has
  1043
+changed which may break any custom tags that use this node class.
  1044
+
1034 1045
 Features deprecated in 1.4
1035 1046
 ==========================
1036 1047
 
3  tests/regressiontests/templates/tests.py
@@ -1204,6 +1204,9 @@ def get_template_tests(self):
1204 1204
             'inheritance40': ("{% extends 'inheritance33' %}{% block opt %}new{{ block.super }}{% endblock %}", {'optional': 1}, '1new23'),
1205 1205
             'inheritance41': ("{% extends 'inheritance36' %}{% block opt %}new{{ block.super }}{% endblock %}", {'numbers': '123'}, '_new1_new2_new3_'),
1206 1206
 
  1207
+            # Expression starting and ending with a quote
  1208
+            'inheritance42': ("{% extends 'inheritance02'|cut:' ' %}", {}, '1234'),
  1209
+
1207 1210
             ### LOADING TAG LIBRARIES #################################################
1208 1211
             'load01': ("{% load testtags subpackage.echo %}{% echo test %} {% echo2 \"test\" %}", {}, "test test"),
1209 1212
             'load02': ("{% load subpackage.echo %}{% echo2 \"test\" %}", {}, "test"),

0 notes on commit 0e54c23

Please sign in to comment.
Something went wrong with that request. Please try again.