#NEWLINE# @ register . tag ( 'for' ) #NEWLINE# def do_for( parser , token ) : #NEWLINE# #INDENT# '\n    Loops over each item in an array.\n\n    For example, to display a list of athletes given ``athlete_list``::\n\n        <ul>\n        {% for athlete in athlete_list %}\n            <li>{{ athlete.name }}</li>\n        {% endfor %}\n        </ul>\n\n    You can loop over a list in reverse by using\n    ``{% for obj in list reversed %}``.\n\n    You can also unpack multiple values from a two-dimensional array::\n\n        {% for key,value in dict.items %}\n            {{ key }}: {{ value }}\n        {% endfor %}\n\n    The ``for`` tag can take an optional ``{% empty %}`` clause that will\n    be displayed if the given array is empty or could not be found::\n\n        <ul>\n          {% for athlete in athlete_list %}\n            <li>{{ athlete.name }}</li>\n          {% empty %}\n            <li>Sorry, no athletes in this list.</li>\n          {% endfor %}\n        <ul>\n\n    The above is equivalent to -- but shorter, cleaner, and possibly faster\n    than -- the following::\n\n        <ul>\n          {% if althete_list %}\n            {% for athlete in athlete_list %}\n              <li>{{ athlete.name }}</li>\n            {% endfor %}\n          {% else %}\n            <li>Sorry, no athletes in this list.</li>\n          {% endif %}\n        </ul>\n\n    The for loop sets a number of variables available within the loop:\n\n        ==========================  ================================================\n        Variable                    Description\n        ==========================  ================================================\n        ``forloop.counter``         The current iteration of the loop (1-indexed)\n        ``forloop.counter0``        The current iteration of the loop (0-indexed)\n        ``forloop.revcounter``      The number of iterations from the end of the\n                                    loop (1-indexed)\n        ``forloop.revcounter0``     The number of iterations from the end of the\n                                    loop (0-indexed)\n        ``forloop.first``           True if this is the first time through the loop\n        ``forloop.last``            True if this is the last time through the loop\n        ``forloop.parentloop``      For nested loops, this is the loop "above" the\n                                    current one\n        ==========================  ================================================\n\n    ' #NEWLINE# bits = token . contents . split ( ) #NEWLINE# if ( len ( bits ) < 4 ) : #NEWLINE# #INDENT# raise TemplateSyntaxError ( ( "'for' statements should have at least four words: %s" % token . contents ) ) #NEWLINE# #UNINDENT# is_reversed = ( bits [ ( - 1 ) ] == 'reversed' ) #NEWLINE# in_index = ( ( is_reversed and ( - 3 ) ) or ( - 2 ) ) #NEWLINE# if ( bits [ in_index ] != 'in' ) : #NEWLINE# #INDENT# raise TemplateSyntaxError ( ( "'for' statements should use the format 'for x in y': %s" % token . contents ) ) #NEWLINE# #UNINDENT# loopvars = re . split ( ' *, *' , ' ' . join ( bits [ 1 : in_index ] ) ) #NEWLINE# for var in loopvars : #NEWLINE# #INDENT# if ( ( not var ) or ( ' ' in var ) ) : #NEWLINE# #INDENT# raise TemplateSyntaxError ( ( "'for' tag received an invalid argument: %s" % token . contents ) ) #NEWLINE# #UNINDENT# #UNINDENT# sequence = parser . compile_filter ( bits [ ( in_index + 1 ) ] ) #NEWLINE# nodelist_loop = parser . parse ( ( 'empty' , 'endfor' ) ) #NEWLINE# token = parser . next_token ( ) #NEWLINE# if ( token . contents == 'empty' ) : #NEWLINE# #INDENT# nodelist_empty = parser . parse ( ( 'endfor' , ) ) #NEWLINE# parser . delete_first_token ( ) #NEWLINE# #UNINDENT# else : #NEWLINE# #INDENT# nodelist_empty = None #NEWLINE# #UNINDENT# return ForNode ( loopvars , sequence , is_reversed , nodelist_loop , nodelist_empty )