forloop.counter
,正如您所发现的,仅指内循环的计数器。您可以使用 访问外循环的计数器forloop.parentloop.counter
,这会有所帮助。
但是,如果您有这样的数据:
list1 = [
{'list2': [
{'name': 'd1 o1'},
{'name': 'd1 o2'}]},
{'list2': [
{'name': 'd2 o1'},
{'name': 'd2 o2'},
{'name': 'd2 o3'}]},
{'list2': [
{'name': 'd3 o1'},
{'name': 'd3 o2'}]}
]
并且您想要产生如下输出:
<tr><td>1 </td><td> d1 o1 </td></tr>
<tr><td>2 </td><td> d1 o2 </td></tr>
<tr><td>3 </td><td> d2 o1 </td></tr>
<tr><td>4 </td><td> d2 o2 </td></tr>
<tr><td>5 </td><td> d2 o3 </td></tr>
<tr><td>6 </td><td> d3 o1 </td></tr>
<tr><td>7 </td><td> d3 o2 </td></tr>
仅仅能够访问父循环是不够的。为此,您有两种选择:
- 按照 Rohan 在评论中的建议,展平列表,或者
- 创建一个可以充当计数器的新模板标签。
展平列表是最简单的选择。在您的视图代码中,如果您像这样重组数据:
flat_list = list({'d': d, 'o': o} for d in list1 for o in d['list2'])
然后,您可以像这样打印列表:
{% for i in flat_list %}
<tr>
<td>{{ forloop.counter}} </td>
<td>{{ i.o.name}}</td>
</tr>
{% endfor %}
但是,这可能是不可能的,具体取决于您的数据。如果这是不可能的,并且列表不能被合理地展平,您将不得不创建一个新的计数器模板标签,其行为可能如下所示:
{% load counter_tags %}
{% counter_from 1 as counter %}
{% for d in list1 %}
{% for o in d.list2 %}
<tr>
<td>{{ counter }} </td>
<td>{{ o.name}}</td>
</tr>
{% endfor %}
{% endfor %}
将以下内容放入templatetags/counter_tags.py
文件中:
import itertools
class Counter(object):
def __init__(self, start, step=1):
self.count = itertools.count(start, step)
def next(self):
return self.count.next()
def __iter__(self):
return self
def __unicode__(self):
return unicode(self.next())
@register.assignment_tag
def counter_from(start, step=1):
return Counter(int(start), int(step))
而且您的模板中有一个独立于循环的计数器!