Python 在Django模板中迭代两个列表

Python 在Django模板中迭代两个列表,python,django,django-templates,Python,Django,Django Templates,我想在django模板中执行以下列表迭代: foo = ['foo', 'bar']; moo = ['moo', 'loo']; for (a, b) in zip(foo, moo): print a, b django代码: {%for a, b in zip(foo, moo)%} {{a}} {{b}} {%endfor%} 我尝试此操作时出现以下错误: File "/base/python_lib/versions/third_party/django-0.96

我想在django模板中执行以下列表迭代:

foo = ['foo', 'bar'];
moo = ['moo', 'loo'];

for (a, b) in zip(foo, moo):
    print a, b
django代码:

{%for a, b in zip(foo, moo)%}
  {{a}}
  {{b}}
{%endfor%}
我尝试此操作时出现以下错误:

File "/base/python_lib/versions/third_party/django-0.96/django/template/defaulttags.py", line 538, in do_for
    raise TemplateSyntaxError, "'for' statements should have either four or five words: %s" % token.contents
我如何做到这一点?

这是可能的

{% for ab in mylist %}
    {{ab.0}}
    {{ab.1}}
{% endfor %}

但是不能在
for
结构中调用
zip
。您必须先将压缩列表存储在另一个变量中,然后对其进行迭代。

您可以在视图中使用
zip

mylist = zip(list1, list2)
context = {
            'mylist': mylist,
        }
return render(request, 'template.html', context)
在模板中使用

{% for item1, item2 in mylist %}
迭代两个列表

这应该适用于Django的所有版本。

我是为了解决这个问题而构建的。自述文件:

安装django multiforloop后,呈现此模板

{% for x in x_list; y in y_list %}
  {{ x }}:{{ y }}
{% endfor %}
在这种背景下

context = {
    "x_list": ('one', 1, 'carrot'),
    "y_list": ('two', 2, 'orange')
}
将输出

one:two
1:2
carrot:orange

您可以在服务器端创建moo对象的foo对象属性

for f, b in zip(foo, bar):
    f.foosBar = b

context = {
    "foo": foo
}
当第二个列表是第一个列表的属性时(通常情况下),这一点尤其清晰

只需将zip定义为:

然后,在模板中:

{%for a, b in first_list|zip:second_list %}
  {{a}}
  {{b}}
{%endfor%}

下面是修改后的{%for%}templatetag,它允许一次迭代多个列表,并在之前对它们进行初始化:

import re

from itertools import izip
from django import template
from django.template.base import TemplateSyntaxError
from django.template.defaulttags import ForNode

register = template.Library()


class ZipExpression(object):
    def __init__(self, var):
        self.var = var

    def resolve(self, *args, **kwargs):
        return izip(*(
            f.resolve(*args, **kwargs) for f in self.var
        ))


@register.tag('for')
def do_for(parser, token):
    """
    For tag with ziping multiple iterables.
    """
    bits = token.contents.split()
    if len(bits) < 4:
        raise TemplateSyntaxError("'foreach' statements should have at least"
                                  " four words: %s" % token.contents)

    is_reversed = False
    try:
        in_index = bits.index('in')
        sequence = bits[in_index+1:]
        if sequence[-1] == 'reversed':
            is_reversed = True
            sequence.pop()
        if not sequence or 'in' in sequence:
            raise ValueError
        sequence = re.split(r' *, *', ' '.join(sequence))
    except ValueError:
        raise TemplateSyntaxError(
            "'foreach' statements should use the format"
            " 'foreach a,b,(...) in x,y,(...)': %s" % token.contents)

    loopvars = re.split(r' *, *', ' '.join(bits[1:in_index]))
    for var in loopvars:
        if not var or ' ' in var:
            raise TemplateSyntaxError("'foreach' tag received an invalid"
                                      " argumewnt: %s" % token.contents)

    if len(sequence) > 1:
        sequence = ZipExpression(map(parser.compile_filter, sequence))
    else:
        sequence = parser.compile_filter(sequence[0])

    nodelist_loop = parser.parse(('empty', 'endfor',))
    token = parser.next_token()
    if token.contents == 'empty':
        nodelist_empty = parser.parse(('endfor',))
        parser.delete_first_token()
    else:
        nodelist_empty = None
    return ForNode(
        loopvars, sequence, is_reversed, nodelist_loop, nodelist_empty)
在views.py中:

foo = ['foo', 'bar']
moo = ['moo', 'loo']
zipped_list = zip(foo,moo)
return render(request,"template.html",{"context":zipped_list}
在template.html中:

{% for f,m in context%}
 {{f}}{{m}}
{% endfor %}

如果
f
是从数据库返回的查询集,那么通过
{{f.required_attribute_name}}

语法a、b在google app engine使用的django模板版本0.96中是不可能的,我想是因为我尝试使用上述语法时出错了。而是执行{%for mylist%}中的项,并使用项.0和项.1。从Ok那里得到的。那么,我的答案可能还是错的。我只知道元组解包在for循环中是可能的,并得出结论,错误一定来自
zip
调用。但没有测试-抱歉,已修复。底线很简单:您不能在模板中进行任何计算;您必须在视图函数中进行所有计算。而且,使用
zip
是一个糟糕的选择;namedtuple是一个更好的主意,因为它使模板更合理。@我想用一个例子详细说明一下。?因为我对python还很陌生,所以没有理解。@Abhi:因为你的问题没有细节,所以很难编一个可能有用的例子。我可以随意猜出你想做什么。相反,从使用
namedtuple
而不是zip开始。如果你还有问题——好吧——发布一个问题。一个棘手的用例是当你有一个
master
列表
['I','you','he']
子列表=[['me','you','him'],['my','your','his'],['mine','your','his']]
。如果你想用
master
迭代每个子列表,你必须在view.Cool应用程序中压缩每个子列表。。但是我无法让它工作:/a另外,我碰巧需要一些能够在小数组上循环多次的东西。不要使用“list”作为变量名,因为这会破坏检测到的内置.Anti-pattern!使用jinja,不要将视图和模板逻辑混用这是一个很好的快速解决方案。请不要用你的评论来迷惑人们,尤其是初学者。完美的解决方案!谢谢这是最好的解决方案,因为我不需要改变背景。谢谢
{% for a,b in foo, moo %}
    {{ a }}
    {{ b }}
{% endfor %}
foo = ['foo', 'bar']
moo = ['moo', 'loo']
zipped_list = zip(foo,moo)
return render(request,"template.html",{"context":zipped_list}
{% for f,m in context%}
 {{f}}{{m}}
{% endfor %}