Changeset 5443
- Timestamp:
- 06/08/07 06:58:03 (1 year ago)
- Files:
-
- django/trunk/django/template/defaulttags.py (modified) (8 diffs)
- django/trunk/docs/templates.txt (modified) (2 diffs)
- django/trunk/tests/regressiontests/templates/tests.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/trunk/django/template/defaulttags.py
r5392 r5443 6 6 from django.conf import settings 7 7 import sys 8 import re 8 9 9 10 register = Library() … … 62 63 63 64 class ForNode(Node): 64 def __init__(self, loopvar , sequence, reversed, nodelist_loop):65 self.loopvar , self.sequence = loopvar, sequence65 def __init__(self, loopvars, sequence, reversed, nodelist_loop): 66 self.loopvars, self.sequence = loopvars, sequence 66 67 self.reversed = reversed 67 68 self.nodelist_loop = nodelist_loop … … 73 74 reversed = '' 74 75 return "<For Node: for %s in %s, tail_len: %d%s>" % \ 75 ( self.loopvar, self.sequence, len(self.nodelist_loop), reversed)76 (', '.join( self.loopvars ), self.sequence, len(self.nodelist_loop), reversed) 76 77 77 78 def __iter__(self): … … 108 109 yield data[index] 109 110 values = reverse(values) 111 unpack = len(self.loopvars) > 1 110 112 for i, item in enumerate(values): 111 113 context['forloop'] = { … … 121 123 'parentloop': parentloop, 122 124 } 123 context[self.loopvar] = item 125 if unpack: 126 # If there are multiple loop variables, unpack the item into them. 127 context.update(dict(zip(self.loopvars, item))) 128 else: 129 context[self.loopvars[0]] = item 124 130 for node in self.nodelist_loop: 125 131 nodelist.append(node.render(context)) 132 if unpack: 133 # The loop variables were pushed on to the context so pop them 134 # off again. This is necessary because the tag lets the length 135 # of loopvars differ to the length of each set of items and we 136 # don't want to leave any vars from the previous loop on the 137 # context. 138 context.pop() 126 139 context.pop() 127 140 return nodelist.render(context) … … 487 500 parser.delete_first_token() 488 501 return FilterNode(filter_expr, nodelist) 489 filter = register.tag("filter", do_filter)502 do_filter = register.tag("filter", do_filter) 490 503 491 504 #@register.tag … … 531 544 </ul> 532 545 533 You can alsoloop over a list in reverse by using546 You can loop over a list in reverse by using 534 547 ``{% for obj in list reversed %}``. 548 549 You can also unpack multiple values from a two-dimensional array:: 550 551 {% for key,value in dict.items %} 552 {{ key }}: {{ value }} 553 {% endfor %} 535 554 536 555 The for loop sets a number of variables available within the loop: … … 553 572 """ 554 573 bits = token.contents.split() 555 if len(bits) == 5 and bits[4] != 'reversed': 556 raise TemplateSyntaxError, "'for' statements with five words should end in 'reversed': %s" % token.contents 557 if len(bits) not in (4, 5): 558 raise TemplateSyntaxError, "'for' statements should have either four or five words: %s" % token.contents 559 if bits[2] != 'in': 560 raise TemplateSyntaxError, "'for' statement must contain 'in' as the second word: %s" % token.contents 561 loopvar = bits[1] 562 sequence = parser.compile_filter(bits[3]) 563 reversed = (len(bits) == 5) 574 if len(bits) < 4: 575 raise TemplateSyntaxError, "'for' statements should have at least four words: %s" % token.contents 576 577 reversed = bits[-1] == 'reversed' 578 in_index = reversed and -3 or -2 579 if bits[in_index] != 'in': 580 raise TemplateSyntaxError, "'for' statements should use the format 'for x in y': %s" % token.contents 581 582 loopvars = re.sub(r' *, *', ',', ' '.join(bits[1:in_index])).split(',') 583 for var in loopvars: 584 if not var or ' ' in var: 585 raise TemplateSyntaxError, "'for' tag received an invalid argument: %s" % token.contents 586 587 sequence = parser.compile_filter(bits[in_index+1]) 564 588 nodelist_loop = parser.parse(('endfor',)) 565 589 parser.delete_first_token() 566 return ForNode(loopvar , sequence, reversed, nodelist_loop)590 return ForNode(loopvars, sequence, reversed, nodelist_loop) 567 591 do_for = register.tag("for", do_for) 568 592 django/trunk/docs/templates.txt
r5436 r5443 448 448 449 449 Loop over each item in an array. For example, to display a list of athletes 450 given ``athlete_list``::450 provided in ``athlete_list``:: 451 451 452 452 <ul> … … 456 456 </ul> 457 457 458 You can also loop over a list in reverse by using ``{% for obj in list reversed %}``. 458 You can loop over a list in reverse by using ``{% for obj in list reversed %}``. 459 460 **New in Django development version** 461 If you need to loop over a list of lists, you can unpack the values 462 in eachs sub-list into a set of known names. For example, if your context contains 463 a list of (x,y) coordinates called ``points``, you could use the following 464 to output the list of points:: 465 466 {% for x, y in points %} 467 There is a point at {{ x }},{{ y }} 468 {% endfor %} 469 470 This can also be useful if you need to access the items in a dictionary. 471 For example, if your context contained a dictionary ``data``, the following 472 would display the keys and values of the dictionary:: 473 474 {% for key, value in data.items %} 475 {{ key }}: {{ value }} 476 {% endfor %} 459 477 460 478 The for loop sets a number of variables available within the loop: django/trunk/tests/regressiontests/templates/tests.py
r5167 r5443 290 290 'for-tag-vars03': ("{% for val in values %}{{ forloop.revcounter }}{% endfor %}", {"values": [6, 6, 6]}, "321"), 291 291 'for-tag-vars04': ("{% for val in values %}{{ forloop.revcounter0 }}{% endfor %}", {"values": [6, 6, 6]}, "210"), 292 'for-tag-unpack01': ("{% for key,value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 293 'for-tag-unpack03': ("{% for key, value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 294 'for-tag-unpack04': ("{% for key , value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 295 'for-tag-unpack05': ("{% for key ,value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 296 'for-tag-unpack06': ("{% for key value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, template.TemplateSyntaxError), 297 'for-tag-unpack07': ("{% for key,,value in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, template.TemplateSyntaxError), 298 'for-tag-unpack08': ("{% for key,value, in items %}{{ key }}:{{ value }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, template.TemplateSyntaxError), 299 # Ensure that a single loopvar doesn't truncate the list in val. 300 'for-tag-unpack09': ("{% for val in items %}{{ val.0 }}:{{ val.1 }}/{% endfor %}", {"items": (('one', 1), ('two', 2))}, "one:1/two:2/"), 301 # Otherwise, silently truncate if the length of loopvars differs to the length of each set of items. 302 'for-tag-unpack10': ("{% for x,y in items %}{{ x }}:{{ y }}/{% endfor %}", {"items": (('one', 1, 'carrot'), ('two', 2, 'orange'))}, "one:1/two:2/"), 303 'for-tag-unpack11': ("{% 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/")), 304 'for-tag-unpack12': ("{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}", {"items": (('one', 1, 'carrot'), ('two', 2))}, ("one:1,carrot/two:2,/", "one:1,carrot/two:2,INVALID/")), 305 'for-tag-unpack13': ("{% for x,y,z in items %}{{ x }}:{{ y }},{{ z }}/{% endfor %}", {"items": (('one', 1, 'carrot'), ('two', 2, 'cheese'))}, ("one:1,carrot/two:2,cheese/", "one:1,carrot/two:2,cheese/")), 292 306 293 307 ### IF TAG ################################################################
