2017-10-12 130 views
1

%的神社文档的Assignments section,根据“作用域行为”小节:补偿用于分配的非持久性内Jinja2的循环

Please keep in mind that it is not possible to set variables inside a block and have them show up outside of it. This also applies to loops. The only exception to that rule are if statements which do not introduce a scope.

我理解else声明中for循环能力,还有像loop.index这样的特殊变量,但这些都不能解决我的问题。

我有一个小部件,它输出的文章,但只有当它们符合一定的标准。为了减少测试用例,这里有一个简单的例子代码:

{% set maxiterations = 3 %} 
{% set iterations = 0 %} 
{% for item in seq %} 
    {% if item == "bar" and iterations < maxiterations %} 
    {{ item.foo }} 
    {% set iterations = iterations + 1 %} 
    {% endif %} 
{% endfor %} 

这当然是行不通的:迭代将总是等于1loop.index不会帮助;我不想计算被跳过的迭代。我该如何解决这个问题?

回答

1

虽然@SumanKalyan是绝对正确的(当它被设置在循环外不能修改循环内迭代) ,我发现他的解决方案,也没有在Jinja2中可用的陈述似乎在我的上下文中被理解。

试图@ SumanKalyan的建议或do像往常一样返回的错误:

CRITICAL: TemplateSyntaxError: Encountered unknown tag 'iterations'. 
Jinja was looking for the following tags: 'elif' or 'else' or 'endif'. 
The innermost block that needs to be closed is 'if'. 

缺少对do支持竟然是因为缺乏这个扩展在我的具体应用(Pelican)的。我可以简单地指定它,但我选择了不同的路线。我发现了一个不同的答案,很大程度上得益于以下认识:Jinja2 for循环支持条件语句。因此:

{% set max_iterations = 3 %} 
{% for item in seq if item == "bar" %} 
    {% if index.loop < max_iterations %} 
     {{ item.foo }} 
    {% endif %} 
{% endfor %} 

这满足的情况下的核心部分:仅输出item.foo如果item == bar;不要使它成为迭代的子集seq的一部分。

在我的实际实现中(超出这里提供的测试用例),我有多个条件。一个需要根据外部设置变量的真实性和特定的循环迭代(第一个,正好发生)跳过项目。如何这样的一个例子就解决了:

{% set baz == true %} 
{% if baz %} 
    {% set max_iterations = 4 %} 
{% else %} 
    {% set max_iterations = 3 %} 
{% endif %} 

{% for item in seq if item == "bar" %} 
    {% if index.loop < max_iterations and not(baz and loop.index == 1) %} 
     {{ item.foo }} 
    {% endif %} 
{% endfor %} 

对于好奇,实际的代码(这也是viewable in context):

{# Only show the widget content if: 
    - There a configured count of articles to display 
    - There's any articles in articles_list 
    - There's at least 2 articles... 
    - ...Or at least 1 article if the widget count is set to 1 #} 

{% if ARTICLES_WIDGET_COUNT and articles_list|length != 0 and (articles_list|length > 1 or ARTICLES_WIDGET_COUNT == 1) %} 
    <aside class="siteFooter_articles widget"> 
     {% if ARTICLES_WIDGET_NAME %} 
      <h1 class="widget_title">{{ ARTICLES_WIDGET_NAME }}</h1> 
     {% endif %} 

     <ol class="imageList list-noType"> 
      {# If this is the index page, the first article is always displayed. 
      It gets skipped inside the loop, so increment the counter #} 
      {% if isindex %} 
       {% set max_iterations = ARTICLES_WIDGET_COUNT + 1 %} 
      {% else %} 
       {% set max_iterations = ARTICLES_WIDGET_COUNT %} 
      {% endif %} 

      {# Skip displaying this article if this is the page for the article being displayed in full 
      If this isn't an article page, always display the item (note the additional condition below for index pages) #} 
      {% for article in articles_list if article.url != thisarticle.url or thisarticle == null %} 
       {# If this is the index page and the first loop iteration, the article to be displayed in the widget would be the same one 
       displayed in full on the page. So, skip it. (Note the counter is incremented before the loop to account for this.) #} 

       {% if not(loop.index == 1 and isindex) %} 
        {% set articles_widget = true %} 
        {% include 'includes/articleitem.html' %} 
       {% endif %} 

       {# If the set number of articles have been added to the widget, we're done here. #} 
       {% if loop.index == max_iterations %} {% break %} {% endif %} 
      {% endfor %} 
     </ol> 

     <p class="readMore"> 
      <a class="readMore_link" href="{{ SITEURL }}/{{ ARTICLES_URL }}">More...</a> 
     </p> 
    </aside> 
{% endif %} 
1

如果您在循环外设置“迭代”,则无法在循环内对其进行修改。 您可以通过使用对象,而不是“重复”标破坏这种行为:

{% set maxiterations = 3 %} 
{% set iterations = [0] %} 
{% for item in seq %} 
    {% if item == "bar" and iterations[0] < maxiterations %} 
    {{ item.foo }} 
    {% iterations.append(iterations.pop() + 1) %} 
    {% endif %} 
{% endfor %} 
+0

当尝试这种解决方案,我得到:'CRITICAL:TemplateSyntaxError:遇到未知标记“迭代”。 Jinja正在寻找以下标签:'elif'或'else'或'endif'。需要关闭的最里面的块是'if'。' – Tohuw

+0

我在'do'语句之前尝试过,但收到相同的错误,但是这次未知标签是'do'。这可能是[Pelican](http://getpelican.com)的限制吗? – Tohuw

+0

发现为什么这不起作用,至少用'做'...看到我下面的答案。 – Tohuw