Jinja2如何进行高级切片
Jinja2 how to perform advanced slicing
我有一个列表,"foos" 如果我有超过 5 个 "foos" 我想针对前 2 个做一些特定的事情,然后针对其余的做一些特定的事情。
所以我有点想要 HTML 中这样的东西:
<div id="accordion">
<p>Foo1<p>
<p>Foo2<p>
<div id="collapseMe" class="panel-collapse collapse">
<p>Foo3<p>
<p>Foo4<p>
etc...
</div>
</div>
<a data-parent="#accordion" href="#collapseMe"><p>Expand</p></a>
所以,我已经在 Jinga2 中解决了这个问题,但解决方案非常难看。我想知道我是否遗漏了什么?
<div id="accordion">
{% for f in foos %}
{% if loop.index <= 2 %}
<p>{{ f.txt }}</p>
{% else %}
{% if loop.index == 3 %}
<div id="collapseMe" class="panel-collapse collapse">
<p>{{ f.txt }}</p>
{% else %}
<p>{{ f.txt }}</p>
{% endif %}
{% endif %}
{% endfor %}
{% if foos | length > 2 %}
</div>
<a data-parent="#accordion" href="#collapseMe"><p>Expand</p></a>
{% endif %}
</div>
虽然这很有效,但我认为一定有更好的方法来做到这一点。不幸的是,据我所知,Jinga2 中的切片函数非常有限,也许还有另一种我还没有采用的解决方法?我也不完全清楚 Batch 函数是如何工作的,但这可能有用吗?
您可以构建或找到一个过滤器,以便在 for 循环之前预先切分您的 foos
列表。
{% for f in foos|slice:"0:10:2" %}
您可以将大部分模板循环逻辑移动到过滤器本身,或者走简单的路线并在列表中使用现有的切片表示法:
from jinja2 import Environment, Undefined
def slice(iterable, pattern):
if iterable is None or isinstance(iterable, Undefined):
return iterable
# convert to list so we can slice
items = list(iterable)
start = None
end = None
stride = None
# split pattern into slice components
if pattern:
tokens = pattern.split(':')
if len(tokens) >= 1:
start = tokens[0]
if len(tokens) >= 2:
end = tokens[1]
if len(tokens) >= 3:
stride = tokens[2];
return items[start:end:stride]
在其他地方,将过滤器添加到您的 Jinja2 环境中。
env = Environment()
env.filters['slice'] = slice
请注意,这是有效的,因为 [:::]
和 [None:None:None]
是相同的切片符号。
我有一个列表,"foos" 如果我有超过 5 个 "foos" 我想针对前 2 个做一些特定的事情,然后针对其余的做一些特定的事情。
所以我有点想要 HTML 中这样的东西:
<div id="accordion">
<p>Foo1<p>
<p>Foo2<p>
<div id="collapseMe" class="panel-collapse collapse">
<p>Foo3<p>
<p>Foo4<p>
etc...
</div>
</div>
<a data-parent="#accordion" href="#collapseMe"><p>Expand</p></a>
所以,我已经在 Jinga2 中解决了这个问题,但解决方案非常难看。我想知道我是否遗漏了什么?
<div id="accordion">
{% for f in foos %}
{% if loop.index <= 2 %}
<p>{{ f.txt }}</p>
{% else %}
{% if loop.index == 3 %}
<div id="collapseMe" class="panel-collapse collapse">
<p>{{ f.txt }}</p>
{% else %}
<p>{{ f.txt }}</p>
{% endif %}
{% endif %}
{% endfor %}
{% if foos | length > 2 %}
</div>
<a data-parent="#accordion" href="#collapseMe"><p>Expand</p></a>
{% endif %}
</div>
虽然这很有效,但我认为一定有更好的方法来做到这一点。不幸的是,据我所知,Jinga2 中的切片函数非常有限,也许还有另一种我还没有采用的解决方法?我也不完全清楚 Batch 函数是如何工作的,但这可能有用吗?
您可以构建或找到一个过滤器,以便在 for 循环之前预先切分您的 foos
列表。
{% for f in foos|slice:"0:10:2" %}
您可以将大部分模板循环逻辑移动到过滤器本身,或者走简单的路线并在列表中使用现有的切片表示法:
from jinja2 import Environment, Undefined
def slice(iterable, pattern):
if iterable is None or isinstance(iterable, Undefined):
return iterable
# convert to list so we can slice
items = list(iterable)
start = None
end = None
stride = None
# split pattern into slice components
if pattern:
tokens = pattern.split(':')
if len(tokens) >= 1:
start = tokens[0]
if len(tokens) >= 2:
end = tokens[1]
if len(tokens) >= 3:
stride = tokens[2];
return items[start:end:stride]
在其他地方,将过滤器添加到您的 Jinja2 环境中。
env = Environment()
env.filters['slice'] = slice
请注意,这是有效的,因为 [:::]
和 [None:None:None]
是相同的切片符号。