如何重置循环计数器?

时间:2013-12-18 19:30:49

标签: django django-templates

我在模板中有这个:

{% for item in items %}
    {% ifchanged item.st2 %}
        <div class="clear"></div>
        <div class="item-title">{{ item.get_st2 }}</div>
    {% endifchanged %}
    <div class="cell {% cycle 'clear tco1' 'tco' 'tco' 'tco2' 'clear tce1' 'tce' 'tce' 'tce2' %}">{{ item.name }}</div>
{% endfor %}

它显示了这样的事情:

------------------ st2 name 1 -------------------

+-----------------------------------------------+
| grey item | grey item | grey item | grey item |
+-----------------------------------------------+
| dark item | dark item | dark item | dark item |
+-----------------------------------------------+
| grey item | grey item | grey item | grey item |
+-----------------------------------------------+
| dark item | dark item | dark item | dark item |
+-----------------------------------------------+
| grey item | grey item | grey item | grey item |
+-----------------------------------------------+

------------------ st2 name 2 -------------------

+-----------------------------------------------+
| grey item | grey item | grey item | grey item |
+-----------------------------------------------+
| dark item | dark item | dark item | dark item |
+-----------------------------------------------+

及其好处。

但如果st2名称上的项目在一行中小于4:

------------------ st2 name 1 -------------------

+-----------------------------------------------+
| grey item | grey item | grey item | grey item |
+-----------------------------------------------+
| dark item | dark item | dark item |
+-----------------------------------+

接下来看起来像这样:

------------------ st2 name 1 -------------------

+-----------------------------------+
| grey item | grey item | grey item | 
+-----------------------------------------------+
| dark item | dark item | dark item | dark item |
+-----------------------------------------------+

因为循环coutner仍然在第四个元素上。

如何重置循环标签?

4 个答案:

答案 0 :(得分:1)

您可以使用cycle代码与silent关键字来声明循环但不生成第一个值。通过给循环标记命名,使用"as",您可以在任何地方插入循环的当前值。另一个带有变量名称的cycle标记会将循环移动到下一个值。 divisibleby标记可用于检查订单项中的最后一项:

{% cycle 'clear tco1' 'tco' 'tco' 'tco2' 'clear tce1' 'tce' 'tce' 'tce2' as cellcls silent %}
{% for item in items %}
    {% ifchanged item.st2 %}
        <div class="clear"></div>
        <div class="item-title">{{ item.get_st2 }}</div>
        {% if not forloop.counter1|divisibleby:"4" %}  {# im not tested it #}
            {% cycle cellcls %}
        {% endif %}
    {% endifchanged %}
    <div class="cell {{cellcls}}">{{ item.name }}</div>
    {% cycle cellcls %}
{% endfor %}

答案 1 :(得分:0)

丑陋,但确实有效:

{% cycle '1' '2' '3' '4' as cellcount silent %}
{% cycle 'tco1' 'tco' 'tco' 'tco2' 'tce1' 'tce' 'tce' 'tce2' as cellcls silent %}
{% for item in items %}
    {% ifchanged item.st2 %}
        {% if not forloop.first %}
            {% if cellcount|add:0 == 2 %}
                {% cycle cellcls %}{% cycle cellcls %}{% cycle cellcls %}
                {% cycle cellcount %}{% cycle cellcount %}{% cycle cellcount %}
            {% endif %}
            {% if cellcount|add:0 == 3 %}
                {% cycle cellcls %}{% cycle cellcls %}
                {% cycle cellcount %}{% cycle cellcount %}
            {% endif %}
            {% if cellcount|add:0 == 4 %}
                {% cycle cellcls %}
                {% cycle cellcount %}
            {% endif %}
        {% endif %}
        <div class="clear"></div>
        <div class="item-title">{{ item.get_st2 }}</div>
    {% endifchanged %}
    <div class="cell {{ cellcls }}" style="{{ cellcount }}">{{ item.name }}</div>
    {% cycle cellcls %}
    {% cycle cellcount %}
{% endfor %}

答案 2 :(得分:0)

我遇到了同样的问题并编写了小型自定义模板标签(适用于django 1.8):

from django import template
import itertools


register = template.Library()


class ResetCycleNode(template.Node):
    def __init__(self, variable_name, cycle_node):
        self.variable_name = variable_name
        self.cycle_node = cycle_node

    def render(self, context):
        cycle_iter = itertools.cycle(self.cycle_node.cyclevars)
        context.render_context[self.cycle_node] = cycle_iter
        context[self.variable_name] = next(cycle_iter).resolve(context)
        return ''


@register.tag
def reset_cycle(parser, token, escape=False):
    args = token.split_contents()

    if len(args) != 2:
        raise TemplateSyntaxError("'reset_cycle' tag requires exactly one argument")

    name = args[1]
    if not hasattr(parser, '_namedCycleNodes'):
        raise TemplateSyntaxError("No named cycles in template. '%s' is not defined" % name)
    if name not in parser._namedCycleNodes:
        raise TemplateSyntaxError("Named cycle '%s' does not exist" % name)

    return ResetCycleNode(name, parser._namedCycleNodes[name])

然后在模板中使用它:

{% cycle 'clear tco1' 'tco' 'tco' 'tco2' 'clear tce1' 'tce' 'tce' 'tce2' as cellclass silent %}
{% for item in items %}
    {% ifchanged item.st2 %}
        <div class="clear"></div>
        <div class="item-title">{{ item.get_st2 }}</div>
        {% reset_cycle cellclass %}
    {% endifchanged %}
    <div class="cell {{ cellclass }}{% cycle cellclass %}">{{ item.name }}</div>
{% endfor %}

答案 3 :(得分:0)

这是一个老问题,但是从Django 1.11开始,有一个内置标记resetcycle似乎可以做OP想要的。