diff --git a/django/template/__init__.py b/django/template/__init__.py index c53d400f3c..29daa76eac 100644 --- a/django/template/__init__.py +++ b/django/template/__init__.py @@ -289,9 +289,14 @@ class Parser(object): return NodeList() def extend_nodelist(self, nodelist, node, token): - if (node.must_be_first and nodelist and - (not isinstance(nodelist[0], TextNode) or len(nodelist) > 2)): - raise TemplateSyntaxError("%r must be the first tag in the template." % node) + if node.must_be_first and nodelist: + try: + if nodelist.contains_nontext: + raise AttributeError + except AttributeError: + raise TemplateSyntaxError("%r must be the first tag in the template." % node) + if isinstance(nodelist, NodeList) and not isinstance(node, TextNode): + nodelist.contains_nontext = True nodelist.append(node) def enter_command(self, command, token): @@ -732,6 +737,10 @@ class Node(object): return nodes class NodeList(list): + # Set to True the first time a non-TextNode is inserted by + # extend_nodelist(). + contains_nontext = False + def render(self, context): bits = [] for node in self: diff --git a/django/template/loader_tags.py b/django/template/loader_tags.py index 716e475807..00ae99bbf9 100644 --- a/django/template/loader_tags.py +++ b/django/template/loader_tags.py @@ -69,14 +69,10 @@ class ExtendsNode(Node): def render(self, context): compiled_parent = self.get_parent(context) - if len(compiled_parent.nodelist) > 1: - n0, n1 = compiled_parent.nodelist[:2] - else: - n0, n1 = compiled_parent.nodelist[0], None - parent_is_child = (isinstance(n0, ExtendsNode) or - (isinstance(n0, TextNode) and isinstance(n1, ExtendsNode))) - if parent_is_child: - extend_node = int(not isinstance(n0, ExtendsNode)) + pos = 0 + while isinstance(compiled_parent.nodelist[pos], TextNode): + pos += 1 + parent_is_child = isinstance(compiled_parent.nodelist[pos], ExtendsNode) parent_blocks = dict([(n.name, n) for n in compiled_parent.nodelist.get_nodes_by_type(BlockNode)]) for block_node in self.nodelist.get_nodes_by_type(BlockNode): # Check for a BlockNode with this node's name, and replace it if found. @@ -88,7 +84,7 @@ class ExtendsNode(Node): # add this BlockNode to the parent's ExtendsNode nodelist, so # it'll be checked when the parent node's render() is called. if parent_is_child: - compiled_parent.nodelist[extend_node].nodelist.append(block_node) + compiled_parent.nodelist[pos].nodelist.append(block_node) else: # Keep any existing parents and add a new one. Used by BlockNode. parent_block.parent = block_node.parent