Ticket #208: 208.4.patch

File 208.4.patch, 6.7 KB (added by SmileyChris, 8 years ago)

new patch, reviewed and refactored

  • django/template/defaulttags.py

     
    3030    def render(self, context):
    3131        self.counter += 1
    3232        value = self.cyclevars[self.counter % self.cyclevars_len]
     33        value = resolve_variable(value, context)
    3334        if self.variable_name:
    3435            context[self.variable_name] = value
    3536        return value
     
    403404    the loop::
    404405
    405406        {% for o in some_list %}
    406             <tr class="{% cycle row1,row2 %}">
     407            <tr class="{% cycle 'row1' 'row2' %}">
    407408                ...
    408409            </tr>
    409410        {% endfor %}
     
    411412    Outside of a loop, give the values a unique name the first time you call
    412413    it, then use that name each sucessive time through::
    413414
    414             <tr class="{% cycle row1,row2,row3 as rowcolors %}">...</tr>
     415            <tr class="{% cycle 'row1' 'row2' 'row3' as rowcolors %}">...</tr>
    415416            <tr class="{% cycle rowcolors %}">...</tr>
    416417            <tr class="{% cycle rowcolors %}">...</tr>
    417418
    418     You can use any number of values, seperated by commas. Make sure not to
    419     put spaces between the values -- only commas.
     419    You can use any number of values, seperated by spaces.
    420420    """
    421421
    422422    # Note: This returns the exact same node on each {% cycle name %} call; that
    423     # is, the node object returned from {% cycle a,b,c as name %} and the one
     423    # is, the node object returned from {% cycle a b c as name %} and the one
    424424    # returned from {% cycle name %} are the exact same object.  This shouldn't
    425425    # cause problems (heh), but if it does, now you know.
    426426    #
     
    429429    # a global variable, which would make cycle names have to be unique across
    430430    # *all* templates.
    431431
    432     args = token.contents.split()
     432    args = token.split_contents()
     433
    433434    if len(args) < 2:
    434         raise TemplateSyntaxError("'Cycle' statement requires at least two arguments")
     435       raise TemplateSyntaxError("'cycle' tag requires at least two arguments")
    435436
    436     elif len(args) == 2 and "," in args[1]:
    437         # {% cycle a,b,c %}
    438         cyclevars = [v for v in args[1].split(",") if v]    # split and kill blanks
    439         return CycleNode(cyclevars)
    440         # {% cycle name %}
     437    if ',' in args[1]:
     438        # Backwards compatibility: {% cycle a,b %} or {% cycle a,b as foo %}
     439        # case.
     440        args[1:2] = ['"%s"' % arg for arg in args[1].split(",")]
    441441
    442     elif len(args) == 2:
     442    if len(args) == 2:
     443        # {% cycle foo %} case
    443444        name = args[1]
    444445        if not hasattr(parser, '_namedCycleNodes'):
    445446            raise TemplateSyntaxError("No named cycles in template: '%s' is not defined" % name)
    446         if name not in parser._namedCycleNodes:
     447        if not name in parser._namedCycleNodes:
    447448            raise TemplateSyntaxError("Named cycle '%s' does not exist" % name)
    448449        return parser._namedCycleNodes[name]
    449450
    450     elif len(args) == 4:
    451         # {% cycle a,b,c as name %}
    452         if args[2] != 'as':
    453             raise TemplateSyntaxError("Second 'cycle' argument must be 'as'")
    454         cyclevars = [v for v in args[1].split(",") if v]    # split and kill blanks
    455         name = args[3]
    456         node = CycleNode(cyclevars, name)
    457 
     451    if len(args) > 4 and args[-2] == 'as':
     452        name = args[-1]
     453        node = CycleNode(args[1:-2], name)
    458454        if not hasattr(parser, '_namedCycleNodes'):
    459455            parser._namedCycleNodes = {}
    460 
    461456        parser._namedCycleNodes[name] = node
    462         return node
    463 
    464457    else:
    465         raise TemplateSyntaxError("Invalid arguments to 'cycle': %s" % args)
     458        node = CycleNode(args[1:])
     459    return node
    466460cycle = register.tag(cycle)
    467461
    468462def debug(parser, token):
  • docs/templates.txt

     
    366366cycle
    367367~~~~~
    368368
    369 Cycle among the given strings each time this tag is encountered.
     369Cycle among the given strings or variables each time this tag is encountered.
    370370
    371 Within a loop, cycles among the given strings each time through the loop::
     371Within a loop, cycles among the given strings/variables each time through the
     372loop::
    372373
    373374    {% for o in some_list %}
    374         <tr class="{% cycle row1,row2 %}">
     375        <tr class="{% cycle 'row1' 'row2' rowvar %}">
    375376            ...
    376377        </tr>
    377378    {% endfor %}
    378 
     379 
    379380Outside of a loop, give the values a unique name the first time you call it,
    380381then use that name each successive time through::
    381382
    382         <tr class="{% cycle row1,row2,row3 as rowcolors %}">...</tr>
     383        <tr class="{% cycle 'row1' 'row2' rowvar as rowcolors %}">...</tr>
    383384        <tr class="{% cycle rowcolors %}">...</tr>
    384385        <tr class="{% cycle rowcolors %}">...</tr>
    385386
    386 You can use any number of values, separated by commas. Make sure not to put
    387 spaces between the values -- only commas.
     387You can use any number of values, separated by spaces. Values enclosed in
     388single (') or double quotes (") are treated as string literals, while values
     389without quotes are assumed to refer to context variables.
    388390
     391The depreciated comma-separated syntax (`{% cycle row1,row2 %}`) is still
     392supported.
     393
    389394debug
    390395~~~~~
    391396
  • tests/regressiontests/templates/tests.py

     
    306306            'cycle06': ('{% cycle a %}', {}, template.TemplateSyntaxError),
    307307            'cycle07': ('{% cycle a,b,c as foo %}{% cycle bar %}', {}, template.TemplateSyntaxError),
    308308            'cycle08': ('{% cycle a,b,c as foo %}{% cycle foo %}{{ foo }}{{ foo }}{% cycle foo %}{{ foo }}', {}, 'abbbcc'),
     309            'cycle09': ("{% for i in test %}{% cycle a,b %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'),
     310            # New format:
     311            'cycle10': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}", {}, 'ab'),
     312            'cycle11': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}", {}, 'abc'),
     313            'cycle12': ("{% cycle 'a' 'b' 'c' as abc %}{% cycle abc %}{% cycle abc %}{% cycle abc %}", {}, 'abca'),
     314            'cycle13': ("{% for i in test %}{% cycle 'a' 'b' %}{{ i }},{% endfor %}", {'test': range(5)}, 'a0,b1,a2,b3,a4,'),
     315            'cycle14': ("{% cycle one two as foo %}{% cycle foo %}", {'one': '1','two': '2'}, '12'),
     316            'cycle13': ("{% for i in test %}{% cycle aye bee %}{{ i }},{% endfor %}", {'test': range(5), 'aye': 'a', 'bee': 'b'}, 'a0,b1,a2,b3,a4,'),
    309317
    310318            ### EXCEPTIONS ############################################################
    311319
Back to Top