Jinja2如何执行高级切片

时间:2016-09-10 04:12:37

标签: python templates flask jinja2

我有一个列表,“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中的切片功能非常有限,也许还有另外一种方法可以解决这个问题吗?我还不完全清楚批处理功能如何工作,但这可能有用吗?

1 个答案:

答案 0 :(得分:1)

您可以构建或查找过滤器,以便在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]是相同的切片表示法。