2017-10-12 2 views
1

Per den Assignments section der Jinja Docs, unter dem „Scoping Behavior“ Unterabschnitt:Ausgleich für die Nicht Persistenz von Zuordnungen innerhalb einer Jinja2 Schleife

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.

Ich verstehe die Fähigkeiten der else Anweisung in der for Schleife und auch spezielle Variablen wie loop.index, aber diese lösen mein Problem nicht.

Ich habe ein Widget, das Artikel ausgibt, aber nur wenn sie bestimmte Kriterien erfüllen. Um den Testfall zu reduzieren, ist hier ein kurzer Beispiel-Code:

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

Dies ist natürlich nicht funktionieren: Iterationen werden immer gleich 1. loop.index wird nicht helfen; Ich möchte keine Iterationen zählen, die übersprungen wurden. Wie kann ich das ansprechen?

Antwort

1

Während @SumanKalyan absolut korrekt ist (man kann nicht Iterationen in der Schleife ändern, wenn es außerhalb der Schleife gesetzt wurde) , Ich fand seine Lösung, noch die do Erklärung, die in Jinja2 verfügbar ist, scheinen in meinem Kontext verstanden zu werden.

Versuch @ SumanKalyan Vorschlag oder do immer wieder Fehler wie:

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'. 

Der Mangel an Unterstützung für do stellte sich heraus, weil der Mangel dieser Erweiterung werden in meinem speziellen Anwendung (Pelican). Ich könnte es einfach spezifizieren, aber ich wählte eine andere Route. Ich fand eine andere Antwort, sehr unterstützt durch die Erkenntnis, dass Jinja2 for Schleifen bedingte Anweisungen unterstützen. Somit gilt:

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

Dies erfüllt ein Kernteil des Gehäuses: nur dann ausgegeben, wenn item.fooitem == bar; mach es nicht Teil der Teilmenge von seq, die über iteriert wird.

In meiner tatsächlichen Implementierung (über den hier vorgestellten Testfall hinaus) hatte ich mehrere Bedingungen. Man musste ein Element überspringen, basierend auf der Wahrheit einer extern gesetzten Variablen und einer bestimmten Schleifeniteration (die erste, wie es passiert). Ein Beispiel, wie dies gelöst:

{% 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 %} 

Für die Neugierigen, der eigentliche Code (die auch 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

Wenn Sie 'Iterationen' außerhalb der Schleife festlegen, können Sie sie nicht innerhalb der Schleife ändern. Sie können dieses Verhalten besiegen, indem ein Objekt mit Hilfe anstatt eine skalare für ‚Iterationen‘:

{% 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

Wenn diese Lösung versucht, erhalte ich: 'KRITISCH: TemplateSyntaxError: Fand unbekannt tag 'Iterationen'. Jinja suchte nach folgenden Tags: 'elif' oder 'else' oder 'endif'. Der innerste Block, der geschlossen werden muss, ist "if". – Tohuw

+0

Ich habe versucht, der Anweisung mit "do" zu folgen, bekomme aber den gleichen Fehler, aber diesmal ist das unbekannte Tag "do". Ist es wahrscheinlich eine Einschränkung von [Pelican] (http://getpelican.com)? – Tohuw

+0

herausgefunden, warum das nicht funktionierte, zumindest mit "do" ... siehe meine untenstehende Antwort. – Tohuw

Verwandte Themen