Ticket #4529: allowmultipleblocks.diff
File allowmultipleblocks.diff, 7.8 KB (added by , 17 years ago) |
---|
-
django/template/__init__.py
190 190 def split_contents(self): 191 191 return list(smart_split(self.contents)) 192 192 193 def __cmp__(self, other): 194 return cmp((self.token_type, self.contents), 195 (other.token_type, other.contents)) 196 193 197 class Lexer(object): 194 198 def __init__(self, template_string, origin): 195 199 self.template_string = template_string … … 251 255 self.tokens = tokens 252 256 self.tags = {} 253 257 self.filters = {} 258 self._token_trackers = {} 254 259 for lib in builtins: 255 260 self.add_library(lib) 256 261 257 def parse(self, parse_until=None): 258 if parse_until is None: parse_until = [] 259 nodelist = self.create_nodelist() 260 while self.tokens: 261 token = self.next_token() 262 if token.token_type == TOKEN_TEXT: 263 self.extend_nodelist(nodelist, TextNode(token.contents), token) 264 elif token.token_type == TOKEN_VAR: 265 if not token.contents: 266 self.empty_variable(token) 267 filter_expression = self.compile_filter(token.contents) 268 var_node = self.create_variable_node(filter_expression) 269 self.extend_nodelist(nodelist, var_node,token) 270 elif token.token_type == TOKEN_BLOCK: 271 if token.contents in parse_until: 272 # put token back on token list so calling code knows why it terminated 273 self.prepend_token(token) 274 return nodelist 275 try: 276 command = token.contents.split()[0] 277 except IndexError: 278 self.empty_block_tag(token) 279 # execute callback function for this tag and append resulting node 280 self.enter_command(command, token) 281 try: 282 compile_func = self.tags[command] 283 except KeyError: 284 self.invalid_block_tag(token, command) 285 try: 286 compiled_result = compile_func(self, token) 287 except TemplateSyntaxError, e: 288 if not self.compile_function_error(token, e): 289 raise 290 self.extend_nodelist(nodelist, compiled_result, token) 291 self.exit_command() 292 if parse_until: 293 self.unclosed_block_tag(parse_until) 294 return nodelist 262 def parse(self, parse_until=None, token_tracker=None): 263 if token_tracker is not None: 264 self._token_trackers[id(token_tracker)] = token_tracker 265 try: 266 if parse_until is None: parse_until = [] 267 nodelist = self.create_nodelist() 268 while self.tokens: 269 token = self.next_token() 270 for x in self._token_trackers.itervalues(): 271 x.append(token) 272 if token.token_type == TOKEN_TEXT: 273 self.extend_nodelist(nodelist, TextNode(token.contents), token) 274 elif token.token_type == TOKEN_VAR: 275 if not token.contents: 276 self.empty_variable(token) 277 filter_expression = self.compile_filter(token.contents) 278 var_node = self.create_variable_node(filter_expression) 279 self.extend_nodelist(nodelist, var_node,token) 280 elif token.token_type == TOKEN_BLOCK: 281 if token.contents in parse_until: 282 # put token back on token list so calling code knows why it terminated 283 self.prepend_token(token) 284 return nodelist 285 try: 286 command = token.contents.split()[0] 287 except IndexError: 288 self.empty_block_tag(token) 289 # execute callback function for this tag and append resulting node 290 self.enter_command(command, token) 291 try: 292 compile_func = self.tags[command] 293 except KeyError: 294 self.invalid_block_tag(token, command) 295 try: 296 compiled_result = compile_func(self, token) 297 except TemplateSyntaxError, e: 298 if not self.compile_function_error(token, e): 299 raise 300 self.extend_nodelist(nodelist, compiled_result, token) 301 self.exit_command() 302 if parse_until: 303 self.unclosed_block_tag(parse_until) 304 return nodelist 305 finally: 306 if token_tracker is not None: 307 del self._token_trackers[id(token_tracker)] 295 308 296 309 def skip_past(self, endtag): 297 310 while self.tokens: … … 934 947 935 948 add_to_builtins('django.template.defaulttags') 936 949 add_to_builtins('django.template.defaultfilters') 950 add_to_builtins('django.template.loader_tags') -
django/template/loader_tags.py
121 121 if len(bits) != 2: 122 122 raise TemplateSyntaxError, "'%s' tag takes only one argument" % bits[0] 123 123 block_name = bits[1] 124 # Keep track of the names of BlockNodes found in this template, so we can125 # check for duplication.126 try:127 if block_name in parser.__loaded_blocks:128 raise TemplateSyntaxError, "'%s' tag with name '%s' appears more than once" % (bits[0], block_name)129 parser.__loaded_blocks.append(block_name)130 except AttributeError: # parser.__loaded_blocks isn't a list yet131 parser.__loaded_blocks = [block_name]132 nodelist = parser.parse(('endblock', 'endblock %s' % block_name))124 # If multiple blocks with the same name are defined in the same template, 125 # all of them must have the same content. To accomplish this, we save 126 # in the parser all blocks which were already encountered, together with 127 # the token list from which each one was constructed. When a new block 128 # with a name that already appeared is encountered, we check if it has 129 # the same token list, and if so the previously created block is returned. 130 tokenlist = [] 131 nodelist = parser.parse(('endblock', 'endblock %s' % block_name), 132 token_tracker=tokenlist) 133 133 parser.delete_first_token() 134 return BlockNode(block_name, nodelist)135 134 135 try: 136 loaded_blocks = parser.__loaded_blocks 137 except AttributeError: 138 loaded_blocks = parser.__loaded_blocks = {} 139 140 try: 141 prev_block, prev_tokenlist = loaded_blocks[block_name] 142 except KeyError: 143 loaded_blocks[block_name] = BlockNode(block_name, nodelist), tokenlist 144 else: 145 if prev_tokenlist != tokenlist: 146 raise TemplateSyntaxError, "'%s' tag with name '%s' appears more than once and doesn't have exactly the same contents in all appearances" % (bits[0], block_name) 147 148 return loaded_blocks[block_name][0] 149 136 150 def do_extends(parser, token): 137 151 """ 138 152 Signal that this template extends a parent template. -
django/template/loader.py
115 115 # If we get here, none of the templates could be loaded 116 116 raise TemplateDoesNotExist, ', '.join(template_name_list) 117 117 118 add_to_builtins('django.template.loader_tags')118 #add_to_builtins('django.template.loader_tags')