Jinja2 how to perform advanced slicing
<p>I've got a list, "foos" and if I've got more than 5 "foos" I want to do something specific to the first 2, and then something specific for the rest.</p>

<p>So I kinda want something like this in HTML:</p>

<pre><code>&lt;div id="accordion"&gt;
    &lt;p&gt;Foo1&lt;p&gt;
    &lt;p&gt;Foo2&lt;p&gt;
    &lt;div id="collapseMe" class="panel-collapse collapse"&gt;
        &lt;p&gt;Foo3&lt;p&gt;
        &lt;p&gt;Foo4&lt;p&gt;
        etc...
    &lt;/div&gt;
&lt;/div&gt;

&lt;a data-parent="#accordion" href="#collapseMe"&gt;&lt;p&gt;Expand&lt;/p&gt;&lt;/a&gt;
</code></pre>

<p>So, I've kinda solved this in Jinga2 but the solution is very ugly. I'm wondering if I'm missing something?</p>

<pre><code>&lt;div id="accordion"&gt;
    {% for f in foos  %}
        {% if loop.index &lt;= 2 %}
            &lt;p&gt;{{ f.txt }}&lt;/p&gt;
        {% else %}
            {% if loop.index == 3 %}
                &lt;div id="collapseMe" class="panel-collapse collapse"&gt;
                    &lt;p&gt;{{ f.txt }}&lt;/p&gt;
            {% else %}
                    &lt;p&gt;{{ f.txt }}&lt;/p&gt;
            {% endif %}
        {% endif %}
    {% endfor %}

    {% if foos | length &gt; 2 %}
    &lt;/div&gt;
    &lt;a data-parent="#accordion" href="#collapseMe"&gt;&lt;p&gt;Expand&lt;/p&gt;&lt;/a&gt;
    {% endif %}
&lt;/div&gt;
</code></pre>

<p>Although this works I'm thinking there must be a better way to do it. Unfortunately slice functions are pretty limited in Jinga2 as far as I can see, maybe there's another way around this that I haven't picked up yet? I'm not fully clear on how the Batch function works either, but that may work?</p>

<p>You could build, or find, a filter to pre-slice your <code>foos</code> list ahead of the for loop.</p>

<pre><code>{% for f in foos|slice:"0:10:2" %}
</code></pre>

<p>You could move most of your template looping logic into the filter itself or go the easy route and use existing slice notation on a list:</p>

<pre><code>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) &gt;= 1:
            start  = tokens[0]
        if len(tokens) &gt;= 2:
            end    = tokens[1]
        if len(tokens) &gt;= 3:
            stride = tokens[2];

    return items[start:end:stride]
</code></pre>

<p>Somewhere else, add the filter to your Jinja2 environment.</p>

<pre><code>env = Environment()
env.filters['slice'] = slice
</code></pre>

<p>Note that this works because <code>[:::]</code> and <code>[None:None:None]</code> are the same slice notation.</p>

python templates flask jinja2