我有两个for循环,两者都有尊严。我想在每次内部迭代期间增加一个计数器。
例如,请考虑以下模板:
from jinja2 import Template
print Template("""
{% set count = 0 -%}
{% for i in 'a', 'b', 'c' -%}
{% for j in 'x', 'y', 'z' -%}
i={{i}}, j={{j}}, count={{count}}
{% set count = count + 1 -%}
{% endfor -%}
{% endfor -%}
""").render()
这不应该打印count=0
到count=8
吗? 不,不是。
i=a, j=x, count=0
i=a, j=y, count=1
i=a, j=z, count=2
i=b, j=x, count=0
i=b, j=y, count=1
i=b, j=z, count=2
i=c, j=x, count=0
i=c, j=y, count=1
i=c, j=z, count=2
是什么给出了?
注意:我不能简单地保存外部loop
变量来计算计数器,因为在我的软件中,内部迭代的数量是可变的。
答案 0 :(得分:14)
使用可变的内部组大小,这将起作用:
from jinja2 import Template
items = [
['foo', 'bar'],
['bax', 'quux', 'ketchup', 'mustard'],
['bacon', 'eggs'],
]
print Template("""
{% set counter = 0 -%}
{% for group in items -%}
{% for item in group -%}
item={{ item }}, count={{ counter + loop.index0 }}
{% endfor -%}
{% set counter = counter + group|length %}
{% endfor -%}
""").render(items=items)
...打印:
item=foo, count=0
item=bar, count=1
item=bax, count=2
item=quux, count=3
item=ketchup, count=4
item=mustard, count=5
item=bacon, count=6
item=eggs, count=7
我想在外面超过一个范围的范围内声明的变量不能分配给什么。
答案 1 :(得分:3)
它确实看起来像一个错误,但如何在模板外部移动一些计算?
from jinja2 import Template
outer_items = list(enumerate("a b c".split()))
inner_items = list(enumerate("x y z".split()))
print Template("""
{% for outer, i in outer_items -%}
{% for inner, j in inner_items -%}
{% set count = outer * num_outer + inner -%}
i={{i}}, j={{j}}, count={{count}}
{% endfor -%}
{% endfor -%}
""").render(outer_items=outer_items,
inner_items=inner_items,
num_outer=len(outer_items))
输出:
i=a, j=x, count=0
i=a, j=y, count=1
i=a, j=z, count=2
i=b, j=x, count=3
i=b, j=y, count=4
i=b, j=z, count=5
i=c, j=x, count=6
i=c, j=y, count=7
i=c, j=z, count=8
答案 2 :(得分:3)
为了解决像这样的用例,我编写了一个小型环境过滤器,用于计算密钥的出现次数。
这是myfilters.py的代码(带有doc测试):
#coding: utf-8
from collections import defaultdict
from jinja2 import environmentfilter
from jinja2.utils import soft_unicode
@environmentfilter
def inc_filter(env, key, value=1, result='value', reset=False):
"""
Count ocurrences of key.
Stores the counter on Jinja's environment.
>>> class Env: pass
>>> env = Env()
>>> inc_filter(env, 'x')
1
>>> inc_filter(env, 'x')
2
>>> inc_filter(env, 'y')
1
>>> inc_filter(env, 'x')
3
>>> inc_filter(env, 'x', reset=True)
1
>>> inc_filter(env, 'x')
2
>>> inc_filter(env, 'x', value=0, reset=True)
0
>>> inc_filter(env, 'x', result=None)
>>> inc_filter(env, 'x', result=False)
u''
>>> inc_filter(env, 'x', result='key')
'x'
>>> inc_filter(env, 'x')
4
"""
if not hasattr(env, 'counters'):
env.counters = defaultdict(int)
if reset:
env.counters[key] = 0
env.counters[key] += value
if result == 'key':
return key
elif result == 'value':
return env.counters[key]
elif result == None:
return None
else:
return soft_unicode('')
## Module doctest
if __name__ == '__main__':
import doctest
doctest.testmod()
设置您的环境注册我们的自定义过滤器:
#coding: utf-8
from jinja2 import Environment, FileSystemLoader
from myfilters import inc_filter
env = Environment(loader=loader=FileSystemLoader('path'))
env.filters['inc'] = inc_filter
t = env.get_template('yourtemplate.txt')
items = [
['foo', 'bar'],
['bax', 'quux', 'ketchup', 'mustard'],
['bacon', 'eggs'],
]
res = t.render(items=items)
在您的模板上,像这样使用它:
{% for group in items -%}
{% for item in group -%}
item={{ item }}, count={{ 'an_identifier'|inc }}
{% endfor -%}
{% endfor -%}
...打印:
item=foo, count=0
item=bar, count=1
item=bax, count=2
item=quux, count=3
item=ketchup, count=4
item=mustard, count=5
item=bacon, count=6
item=eggs, count=7
答案 3 :(得分:1)
内置全局函数cycler()提供与循环无关的值循环。使用相同的想法,您可以像这样定义自己的counter()
函数:
env=Environment(...) # create environment
env.globals['counter']=_Counter # define global function
env.get_template(...).render(...) # render template
这是实现该功能的类:
class _Counter(object):
def __init__(self, start_value=1):
self.value=start_value
def current(self):
return self.value
def next(self):
v=self.value
self.value+=1
return v
以下是如何使用它:
{% set cnt=counter(5) %}
item #{{ cnt.next() }}
item #{{ cnt.next() }}
item #{{ cnt.next() }}
item #{{ cnt.next() }}
它会呈现:
item #5
item #6
item #7
item #8
答案 4 :(得分:0)
无需添加计数器。您可以像这样访问外部循环索引:
{% for i in 'a', 'b', 'c' -%}
{% set outerloop = loop %}
{% for j in 'x', 'y', 'z' -%}
i={{i}}, j={{j}}, count={{outerloop.index0 * loop|length + loop.index0}}
{% endfor -%}
{% endfor -%}