Ticket #3523: for_tag.3.patch
File for_tag.3.patch, 7.1 KB (added by , 18 years ago) |
---|
-
django/template/defaulttags.py
5 5 from django.template import get_library, Library, InvalidTemplateLibrary 6 6 from django.conf import settings 7 7 import sys 8 import string 8 9 9 10 register = Library() 10 11 … … 58 59 return '' 59 60 60 61 class ForNode(Node): 61 def __init__(self, loopvar , sequence, reversed, nodelist_loop):62 self.loopvar , self.sequence = loopvar, sequence62 def __init__(self, loopvars, sequence, reversed, nodelist_loop): 63 self.loopvars, self.sequence = loopvars, sequence 63 64 self.reversed = reversed 64 65 self.nodelist_loop = nodelist_loop 65 66 67 66 68 def __repr__(self): 67 69 if self.reversed: 68 70 reversed = ' reversed' 69 71 else: 70 72 reversed = '' 71 73 return "<For Node: for %s in %s, tail_len: %d%s>" % \ 72 ( self.loopvar, self.sequence, len(self.nodelist_loop), reversed)74 (', '.join( self.loopvars ), self.sequence, len(self.nodelist_loop), reversed) 73 75 74 76 def __iter__(self): 75 77 for node in self.nodelist_loop: … … 104 106 for index in range(len(data)-1, -1, -1): 105 107 yield data[index] 106 108 values = reverse(values) 109 unpack = len(self.loopvars) > 1 107 110 for i, item in enumerate(values): 108 111 context['forloop'] = { 109 112 # shortcuts for current loop iteration number … … 117 120 'last': (i == len_values - 1), 118 121 'parentloop': parentloop, 119 122 } 120 context[self.loopvar] = item 123 if unpack: 124 # If multiple loop variables, unpack the item to them. 125 context.update(dict(zip(self.loopvars, item))) 126 else: 127 context[self.loopvars[0]] = item 121 128 for node in self.nodelist_loop: 122 129 nodelist.append(node.render(context)) 123 130 context.pop() … … 438 445 nodelist = parser.parse(('endfilter',)) 439 446 parser.delete_first_token() 440 447 return FilterNode(filter_expr, nodelist) 441 filter = register.tag("filter", do_filter)448 do_filter = register.tag("filter", do_filter) 442 449 443 450 #@register.tag 444 451 def firstof(parser, token): … … 482 489 {% endfor %} 483 490 </ul> 484 491 485 You can alsoloop over a list in reverse by using492 You can loop over a list in reverse by using 486 493 ``{% for obj in list reversed %}``. 494 495 You can also unpack multiple values from a two-dimensional array:: 496 497 {% for key,value in dict.items %} 498 {{ key }}: {{ value }} 499 {% endfor %} 487 500 488 501 The for loop sets a number of variables available within the loop: 489 502 … … 504 517 505 518 """ 506 519 bits = token.contents.split() 507 if len(bits) == 5 and bits[4] != 'reversed': 508 raise TemplateSyntaxError, "'for' statements with five words should end in 'reversed': %s" % token.contents 509 if len(bits) not in (4, 5): 510 raise TemplateSyntaxError, "'for' statements should have either four or five words: %s" % token.contents 511 if bits[2] != 'in': 512 raise TemplateSyntaxError, "'for' statement must contain 'in' as the second word: %s" % token.contents 513 loopvar = bits[1] 514 sequence = parser.compile_filter(bits[3]) 515 reversed = (len(bits) == 5) 520 if len(bits) < 4: 521 raise TemplateSyntaxError, "'for' statements should have at least four words: %s" % token.contents 522 523 reversed = bits[-1] == 'reversed' 524 in_index = reversed and -3 or -2 525 if bits[in_index] != 'in': 526 raise TemplateSyntaxError, "'for' statements should use the format 'for x in y': %s" % token.contents 527 528 loopvars = [] 529 for bit in bits[1:in_index]: 530 loopvars.extend(bit.split(',')) 531 loopvars = map(string.strip, loopvars) 532 loopvars = filter(None, loopvars) 533 534 sequence = parser.compile_filter(bits[in_index+1]) 516 535 nodelist_loop = parser.parse(('endfor',)) 517 536 parser.delete_first_token() 518 return ForNode(loopvar , sequence, reversed, nodelist_loop)537 return ForNode(loopvars, sequence, reversed, nodelist_loop) 519 538 do_for = register.tag("for", do_for) 520 539 521 540 def do_ifequal(parser, token, negate): -
docs/templates.txt
435 435 ~~~ 436 436 437 437 Loop over each item in an array. For example, to display a list of athletes 438 given ``athlete_list``::438 provided in ``athlete_list``:: 439 439 440 440 <ul> 441 441 {% for athlete in athlete_list %} … … 443 443 {% endfor %} 444 444 </ul> 445 445 446 You can alsoloop over a list in reverse by using ``{% for obj in list reversed %}``.446 You can loop over a list in reverse by using ``{% for obj in list reversed %}``. 447 447 448 For advanced use, you can unpack multiple values from a list of fixed length 449 lists. For example, if dict was a Python dictionary:: 450 451 {% for key, value in dict.items %} 452 {{ key }}: {{ value }} 453 {% endfor %} 454 448 455 The for loop sets a number of variables available within the loop: 449 456 450 457 ========================== ================================================ -
tests/regressiontests/templates/tests.py
252 252 'for-tag-vars02': ("{% for val in values %}{{ forloop.counter0 }}{% endfor %}", {"values": [6, 6, 6]}, "012"), 253 253 'for-tag-vars03': ("{% for val in values %}{{ forloop.revcounter }}{% endfor %}", {"values": [6, 6, 6]}, "321"), 254 254 'for-tag-vars04': ("{% for val in values %}{{ forloop.revcounter0 }}{% endfor %}", {"values": [6, 6, 6]}, "210"), 255 'for-tag-unpack01': ("{% for key,value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 256 'for-tag-unpack02': ("{% for key, value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 257 'for-tag-unpack03': ("{% for key value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 258 # Ensure that a single loopvar doesn't truncate the list in val. 259 'for-tag-unpack04': ("{% for val in items %}{{ val.0 }}:{{ val.1 }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 260 # Otherwise, silently truncate if the length of loopvars differs to the length of each set of items. 261 'for-tag-unpack05': ("{% for x,y in items %}{{ x }}:{{ y }}/{% endfor %}", {"items": (('one', 1, 'carrot'), ('two', 2, 'orange'))}, "one:1/two:2/"), 262 'for-tag-unpack06': ("{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, ("one:1,/two:2,/", "one:1,INVALID/two:2,INVALID/")), 255 263 256 264 ### IF TAG ################################################################ 257 265 'if-tag01': ("{% if foo %}yes{% else %}no{% endif %}", {"foo": True}, "yes"),