Ticket #5172: simple-for.patch

File simple-for.patch, 6.0 KB (added by SmileyChris, 8 years ago)
  • django/template/defaulttags.py

     
    7979            reversed = ' reversed'
    8080        else:
    8181            reversed = ''
    82         return "<For Node: for %s in %s, tail_len: %d%s>" % \
    83             (', '.join( self.loopvars ), self.sequence, len(self.nodelist_loop), reversed)
     82        loopvars = loopvars and '%s in ' % ', '.join(self.loopvars) or ''
     83        return "<For Node: for %s%s, length of: %d%s>" % (loopvars,
     84                 self.sequence, len(self.nodelist_loop), reversed)
    8485
    8586    def __iter__(self):
    8687        for node in self.nodelist_loop:
     
    106107            values = []
    107108        if values is None:
    108109            values = []
     110        if not self.loopvars:
     111            # It's a simple integer-based loop
     112            try:
     113                values = range(int(values))
     114            except (ValueError, TypeError):
     115                values = []
    109116        if not hasattr(values, '__len__'):
    110117            values = list(values)
    111118        len_values = len(values)
     
    128135            if unpack:
    129136                # If there are multiple loop variables, unpack the item into them.
    130137                context.update(dict(zip(self.loopvars, item)))
    131             else:
     138            elif self.loopvars:
    132139                context[self.loopvars[0]] = item
    133140            for node in self.nodelist_loop:
    134141                nodelist.append(node.render(context))
     
    567574                                    current one
    568575        ==========================  ================================================
    569576
     577    You can also set up a simple integer loop by passing in just an integer.
     578    Nothing will be added to the context except for the ``forloop`` variable.
     579
     580        {% for 5 %}
     581            loop: {{ forloop.counter }}
     582        {% endfor %}
     583        {% for my_integer %}
     584            loop: {{ forloop.counter }}
     585        {% endfor %}
    570586    """
    571587    bits = token.contents.split()
    572     if len(bits) < 4:
    573         raise TemplateSyntaxError, "'for' statements should have at least four words: %s" % token.contents
     588    if len(bits) < 4 and len(bits) != 2:
     589        raise TemplateSyntaxError, ("Invalid format for 'for' tag: %s" %
     590                                    token.contents)
    574591
    575     reversed = bits[-1] == 'reversed'
    576     in_index = reversed and -3 or -2
    577     if bits[in_index] != 'in':
    578         raise TemplateSyntaxError, "'for' statements should use the format 'for x in y': %s" % token.contents
    579 
    580     loopvars = re.sub(r' *, *', ',', ' '.join(bits[1:in_index])).split(',')
    581     for var in loopvars:
    582         if not var or ' ' in var:
    583             raise TemplateSyntaxError, "'for' tag received an invalid argument: %s" % token.contents
    584 
    585     sequence = parser.compile_filter(bits[in_index+1])
     592    if len(bits) == 2:
     593        reversed = False
     594        loopvars = []
     595        sequence = parser.compile_filter(bits[1])
     596    else:
     597        reversed = bits[-1] == 'reversed'
     598        in_index = reversed and -3 or -2
     599        if bits[in_index] != 'in':
     600            raise TemplateSyntaxError, "'for' statements should use the format 'for x in y': %s" % token.contents
     601   
     602        loopvars = re.sub(r' *, *', ',', ' '.join(bits[1:in_index])).split(',')
     603        for var in loopvars:
     604            if not var or ' ' in var:
     605                raise TemplateSyntaxError, "'for' tag received an invalid argument: %s" % token.contents
     606   
     607        sequence = parser.compile_filter(bits[in_index+1])
    586608    nodelist_loop = parser.parse(('endfor',))
    587609    parser.delete_first_token()
    588610    return ForNode(loopvars, sequence, reversed, nodelist_loop)
  • docs/templates.txt

     
    492492                                current one
    493493    ==========================  ================================================
    494494
     495**New in Django development version**
     496You can also set up a simple loop by passing just an integer variable (or
     497constant)::
     498
     499    {% for var %}
     500        loop: {{ forloop.counter }}
     501    {% endfor %}
     502
    495503if
    496504~~
    497505
  • tests/regressiontests/templates/tests.py

     
    356356            '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/")),
    357357            '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/")),
    358358            '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/")),
     359            'for-tag-simple01': ("{% for 5 %}{{ forloop.counter }},{% endfor %}", {}, "1,2,3,4,5,"),
     360            'for-tag-simple02': ('{% for "5" %}{{ forloop.counter }},{% endfor %}', {}, "1,2,3,4,5,"),
     361            'for-tag-simple03': ('{% for "not-a-number" %}{{ forloop.counter }},{% endfor %}', {}, ""),
     362            'for-tag-simple04': ('{% for number %}{{ forloop.counter }},{% endfor %}', {'number': 5}, "1,2,3,4,5,"),
     363            'for-tag-simple05': ('{% for number %}{{ forloop.counter }},{% endfor %}', {'number': '5'}, "1,2,3,4,5,"),
     364            'for-tag-simple06': ('{% for number %}{{ forloop.counter }},{% endfor %}', {'number': 'not-a-number'}, ""),
     365            'for-tag-simple07': ('{% for number %}{{ forloop.counter }},{% endfor %}', {}, ""),
    359366
    360367            ### IF TAG ################################################################
    361368            'if-tag01': ("{% if foo %}yes{% else %}no{% endif %}", {"foo": True}, "yes"),
Back to Top