61

Django 模板提供了用于在模板中不同点(或模板中的 for 循环)的多个值之间交替的内置标签,但是当在s 定义cycle之外的范围内访问该标签时,该标签不会重置。cycle即,如果您的模板中有两个或多个列表,那么您希望使用一些 css 定义的所有行oddeven,列表的第一行将在最后一个离开的地方,而不是新的迭代从选择 (oddeven)

例如,在下面的代码中,如果第一个博客有奇数个条目,那么第二个博客中的第一个条目将以 开头even,而我希望它以 开头odd

{% for blog in blogs %}
  {% for entry in blog.entries %}
    <div class="{% cycle 'odd' 'even' %}" id="{{entry.id}}">
      {{entry.text}}
    </div>
  {% endfor %}
{% endfor %}

我尝试通过修补resetcycle此处提供的标签来避免这种情况:

Django票:循环标签在超出范围后应重置

无济于事。(代码对我不起作用。)

我也尝试将我的内部循环移动到自定义标记中,但这也不起作用,可能是因为编译/渲染循环将循环移回了外部循环?(不管为什么,它对我不起作用。)

我怎样才能完成这个简单的任务!?我不希望在我的视图中使用预编译的这些信息创建数据结构;这似乎没有必要。提前致谢。

4

7 回答 7

114

最简单的解决方法(在修复并应用 resetcycle 补丁之前)是使用带有 forloop.counter 的内置“divisibleby”过滤器:

{% for entry in blog.entries %}
  <div class="{% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}" id="{{ entry.id }}">
    {{ entry.text }}
  </div>
{% endfor %}

有点冗长,但不难理解,而且效果很好。

于 2009-01-20T02:15:37.753 回答
22

https://docs.djangoproject.com/en/1.8/ref/templates/builtins/#cycle

{% for o in some_list %}
    <tr class="{% cycle 'row1' 'row2' %}">
        ...
    </tr>
{% endfor %}
于 2015-06-18T16:45:33.397 回答
3

放弃使用Jinja2 模板系统

我放弃了 django 模板语言,它的用途非常有限。Jinja2 使用与 django 模板相同的语法,但在它之上添加了许多增强功能。

编辑/注意(我知道这听起来像是一个小问题的大转变,但实际上我敢打赌你总是发现自己在与 django 中的默认模板系统作斗争,所以它真的很值得,我相信它会让你更有效率从长远来看。)

你可以阅读它的作者写的这篇文章,虽然它是技术性的,但他提到了 django 中 {% cycle %} 标签的问题。

Jinja 没有循环标签,它在循环上有一个循环方法:

{% for user in users %}
    <li class="{{ loop.cycle('odd', 'even') }}">{{ user }}</li>
{% endfor %}

Jinja2 的一个主要优点是它允许您使用逻辑进行演示,所以如果您有一个图片列表,您可以将它们放在一个表格中,因为您可以在表格中每隔 N 个元素开始一个新行,看,例如,您可以这样做:

{% if loop.index is divisibleby(5) %}   
     </tr>
     {% if not loop.last %}
     <tr>
     {% endif %}
{% endif %}

您还可以使用数学表达式:

{% if x > 10 %}

并且您可以直接访问您的 python 函数(但需要一些设置来指定应该为模板公开哪些函数)

{% for item in normal_python_function_that_returns_a_query_or_a_list() %}

甚至设置变量..

{% set variable_name = function_that_returns_an_object_or_something() %} 
于 2009-01-19T21:33:43.017 回答
3

您可以使用标记cycleresetcycle(Django 1.11 中的新功能)调用(来自https://docs.djangoproject.com/en/1.11/ref/templates/builtins/#std:templatetag-resetcycle):

{% for blog in blogs %}
  {% cycle 'odd' 'even' as rowcolors silent %}
  {% resetcycle rowcolors %}
  {% for entry in blog.entries %}
    {% cycle rowcolors %}
    <div class="{{ rowcolors }}" id="{{entry.id}}">
      {{ entry.text }}
    </div>
  {% endfor %}
{% endfor %}
于 2017-12-20T12:13:09.990 回答
2

我最终这样做了,使用 forloop.counter0 - 效果很好!

{% for product in products %}

    {% if forloop.counter0|divisibleby:4 %}<div class="clear"></div>{% endif %}

    <div class="product {% if forloop.counter0|divisibleby:4 %}col{% else %}col20{% endif    %}">
        Lorem Ipsum is simply dummy text
    </div>

{% endfor %}
于 2011-04-14T08:33:37.373 回答
1

最简单的答案可能是:“放弃并使用 jQuery。” 如果这是可以接受的,那么它可能比与 Django 的模板为如此简单的事情而斗争更容易。

于 2009-01-19T21:20:03.747 回答
-5

有一种方法可以在服务器端使用不保留所有条目的同时副本的迭代器:

import itertools
return render_to_response('template.html',
  {
    "flattened_entries": itertools.chain(*(blog.entries for blog in blogs)),
  })
于 2009-01-19T23:25:35.727 回答