Search code examples
jinja2pelican

Why does pelican/jinja2 not set the variable again?


I have the following script:

<div class="blog-archives">
    {% set last_year = 0 %}
    {% for article in dates %}
        {% set year = article.date.strftime('%Y') %}
        {% if last_year != year %}
            <h2 id="{{year }}" title="last_year={{last_year}}"><a href="#{{year}}">{{ year }}</a></h2>
            {% set last_year = year %}
        {% endif %}
        {% set next_year = 0 %}
        {% if not loop.last %}
            {% set next = loop.index0 + 1 %}
            {% set next_article = dates[next] %}
            {% set next_year = next_article.date.strftime('%Y') %}
        {% endif %}
        {% if next_year != year %}
            <article class="last-entry-of-year">
        {% else %}
            <article>
        {% endif %}
        <a href="{{ SITEURL }}/{{ article.url }}">{{ article.title }} {%if article.subtitle %} <small> {{ article.subtitle }} </small> {% endif %} </a>
        <time pubdate="pubdate" datetime="{{ article.date.isoformat() }}">{{ article.locale_date }}</time>
        </article>
    {% endfor %}
</div>

which I thought would result in something like this:

enter image description here

But actually I get

enter image description here

The problem is that {% set last_year = year %} seems not to be executed - the value of last_year is always 0. Does anybody know why and how to fix it?


Solution

  • Unlike Python, in Jinja2 a for loop have its own namespace; therefore the variables you set within the loop is local to the loop, and once outside the loop, the variable of the same name would revert to the one of the outer scope.

    You can use the namespace object to get around this issue:

    {% set ns = namespace(last_year=0) %}
    {% for article in dates %}
        {% set year = article.date.strftime('%Y') %}
        {% if ns.last_year != year %}
            <h2 id="{{year }}" title="last_year={{ns.last_year}}"><a href="#{{year}}">{{ year }}</a></h2>
            {% set ns.last_year = year %}
    

    Please see the documentation of namespace for details.