在Django模板中将For循环迭代作为列表索引
我正在搭建一个django网页,但遇到了一些问题,就是我不知道怎么在模板中使用for循环的当前迭代来处理多个列表。
{% for num in loopRange %}
<tr>
{% for num2 in subRange %}
<td>{% cycle list1 list2 list3 list4 %}</td>
{% endfor %}
</tr>
{% endfor %}
我在stackoverflow上找到了一些类似的问题,尝试使用cycle这个功能,但结果是每次都打印出列表中的所有成员——这其实并不意外,但我就是搞不明白该怎么做。
我有多个内容相似的列表,每个列表都是一行中的一列。所以,如果用python来拼接字符串的话,大概就是这个样子:
for i in xrange(5):
string = list1[i] + list2[i] + list3[i] + list 4[i]
基本上就是这样。我把每个列表作为上下文传入,还有两个xranges(在第一个例子中是loopRange和Subrange),我需要五行(每个列表有五个成员)和四列(四个列表)。
补充:简单来说,我想用列表的索引来引用,比如foo[bar],在django中是用foo.bar来表示,但bar显然不能是一个整数,也不能作为内容传入一个可迭代的范围。
谢谢!
3 个回答
0
如果你真的想在模板里做这个,有一些原因的话,你可以写一个自定义模板标签来帮你实现:
#app/templatetags/zip.py
from django import template
register = template.Library()
class Zipper(template.Node):
def __init__(self, format_string, var_name):
self.format_string = format_string
self.var_name = var_name
def render(self, context):
zippables = [context[tok] for tok in self.format_string.split()]
import pdb; pdb.set_trace()
context[self.var_name] = zip(*zippables)
return ''
import re
@register.tag(name="zip")
def do_zip(parser, token):
try:
# Splitting by None == splitting by spaces.
tag_name, arg = token.contents.split(None, 1)
except ValueError:
raise template.TemplateSyntaxError("%r tag requires arguments" % token.contents.split()[0])
m = re.search(r'(.*?) as (\w+)', arg)
if not m:
raise template.TemplateSyntaxError("%r tag had invalid arguments" % tag_name)
format_string, var_name = m.groups()
return Zipper(format_string, var_name)
注意:在Django 1.4中,这种写法会变得简单很多,因为新增了assignment_tag
。
然后,你可以这样使用它:
{%load zip%}
{% zip list1 list2 list3 list4 as list_of_rows %}
你可以在那个代码块里随意使用list_of_rows
,包括在两个嵌套的循环里面。
1
你可以简单地创建一个过滤器,从列表中返回一个项目:
@register.filter
def get_item(row, i):
try:
return row[i]
except IndexError:
return ''
然后:
{{ list1|get_item:num2 }}
3
我认为最好的方法是在把数据传给模板之前,先在视图中处理好这些数据。
比如,可以使用内置的 zip
函数来根据包含列的列表创建行的列表:
rows = zip(list1, list2, list3, list4)
之后,模板可以逐行遍历这些行,如果需要的话,可以通过索引来访问列:
{% for row in rows %}
{{row.0}} {{row.1}} {{row.2}} {{row.3}}
{% endfor %}