2010-06-28 222 views

回答

22

你有两个选择:

1.定义你的对象,以便您可以访问参数等项目

for x in list: 
    {{x.item1}}, {{x.item2}}, {{x.item3}} 

请注意,您必须通过三个相结合,以弥补列表清单:

lst = [{'item1': t[0], 'item2': t[1], 'item3':t[2]} for t in zip(list_a, list_b, list_c)] 

2.您可以定义自己的过滤

from django import template 

register = template.Library() 

@register.filter(name='list_iter') 
def list_iter(lists): 
    list_a, list_b, list_c = lists 

    for x, y, z in zip(list_a, list_b, list_c): 
     yield (x, y, z) 

# test the filter 
for x in list_iter((list_a, list_b, list_c)): 
    print x 

filter documentation

+0

谢谢!完美解决方案 – demos 2010-06-29 04:11:17

+0

您将如何在模板中使用解决方案2? – webtweakers 2014-02-26 09:28:50

6

滥用Django模板:

{% for x in list_a %} 
{% with forloop.counter|cut:" " as index %} 
    {{ x }}, 
    {{ list_b|slice:index|last }}, 
    {{ list_c|slice:index|last }} <br/> 
{% endwith %} 
{% endfor %} 

,但从来没有做到这一点!只需在您的视图中使用zip。

+1

不错的破解! :)有一天可能会派上用场。 – demos 2010-06-29 04:11:36

+0

好的黑客对我很有帮助 – 2015-04-30 09:14:44

1

自定义模板标签

from django import template 

register = template.Library() 

def parse_tokens(parser, bits): 
    """ 
    Parse a tag bits (split tokens) and return a list on kwargs (from bits of the fu=bar) and a list of arguments. 
    """ 

    kwargs = {} 
    args = [] 
    for bit in bits[1:]: 
     try: 
      try: 
       pair = bit.split('=') 
       kwargs[str(pair[0])] = parser.compile_filter(pair[1]) 
      except IndexError: 
       args.append(parser.compile_filter(bit)) 
     except TypeError: 
      raise template.TemplateSyntaxError('Bad argument "%s" for tag "%s"' % (bit, bits[0])) 

    return args, kwargs 

class ZipLongestNode(template.Node): 
    """ 
    Zip multiple lists into one using the longest to determine the size 

    Usage: {% zip_longest list1 list2 <list3...> as items %} 
    """ 
    def __init__(self, *args, **kwargs): 
     self.lists = args 
     self.varname = kwargs['varname'] 

    def render(self, context): 
     lists = [e.resolve(context) for e in self.lists] 

     if self.varname is not None: 
      context[self.varname] = [i for i in map(lambda *a: a, *lists)] 
     return '' 

@register.tag 
def zip_longest(parser, token): 
    bits = token.contents.split() 
    varname = None 
    if bits[-2] == 'as': 
     varname = bits[-1] 
     del bits[-2:] 
    else: 
     # raise exception 
     pass 
    args, kwargs = parse_tokens(parser, bits) 

    if varname: 
     kwargs['varname'] = varname 

    return ZipLongestNode(*args, **kwargs) 

用法:

{% zip_longest list1 list2 as items %} 

这可以让你通过2名或多个列表标签,然后在项目变量进行迭代。如果你使用两个以上的列表,那么不幸的是你需要循环。然而,随着两份名单,我使用的第一和最后一个过滤器内环路这样的:

{% for item in items %} 
    {% with item|first as one %} 
    {% with item|last as two %} 
    <p>{{ one }}</p> 
    <p>{{ two }}</p> 
    {% endwith %} 
    {% endwith %} 
{% endfor %} 

然而,因建了这一切,它可能是更好的做到这一点的看法!

Python的Itertools

你也应该考虑Python的itertools,它具有izip_longest方法,它有两个或多个列表。它使用最长的列表作为一个返回列表来确定大小(如果您希望它连接到最短列表,那么看起来不会比izip更远)。您可以使用fillvalue关键字来选择填充空值的内容,但默认情况下为None。

izip_longest和izip都返回一个迭代器而不是一个列表,所以你可以看到一些大型网站的性能提升。

重要的是要注意,izip_longest可能会稍微超过必要的数据库,这取决于它如何确定每个列表的长度(执行count()将是对db的额外调用)。然而,我还没有设法可靠地测试这一点,只有当你不得不扩大规模时才会出现问题。