Jak inkrementować zmienną w pętli for w szablonie Jinja?

83

Chciałbym zrobić coś takiego:

zmienna p pochodzi z test.py, która jest listą [„a”, „b”, „c”, „d”]

{% for i in p %}
{{variable++}}
{{variable}}

wynik to:
1 2 3 4

user422100
źródło

Odpowiedzi:

157

Możesz użyć loop.index:

{% for i in p %}
  {{ loop.index }}
{% endfor %}

Sprawdź dokumentację projektanta szablonów .

W nowszych wersjach, ze względu na zasady określania zakresu, następujące elementy nie działałyby:

{% set count = 1 %}
{% for i in p %}
  {{ count }}
  {% set count = count + 1 %}
{% endfor %}
zeekay
źródło
Użyj tej odpowiedzi, aby rozwiązać problem z
zakresem
68

Po 2.10, aby rozwiązać problem z zakresem, możesz zrobić coś takiego:

{% set count = namespace(value=0) %}
{% for i in p %}
  {{ count.value }}
  {% set count.value = count.value + 1 %}
{% endfor %}
Patrick José Pereira
źródło
1
Pojawia się błąd: TemplateSyntaxError at / listing / Invalid block tag on line 145: „set”, oczekiwany „endblock”. Czy zapomniałeś zarejestrować lub załadować ten tag? Włączone: {% set count = namespace (value = 0)%} Masz pojęcie o przyczynie?
Andrew,
56

Jak mówi Jeroen, istnieją problemy z zasięgiem: jeśli ustawisz „count” poza pętlą, nie możesz go zmodyfikować wewnątrz pętli.

Możesz pokonać to zachowanie, używając obiektu zamiast skalara dla `` count '':

{% set count = [1] %}

Możesz teraz manipulować licznikiem wewnątrz pętli lub nawet% włączania%. Oto jak liczę przyrosty (tak, jest niezdarny, ale cóż):

{% if count.append(count.pop() + 1) %}{% endif %} {# increment count by 1 #}
Peter Hollingsworth
źródło
Peter Hollingsworth. Wielkie dzięki za te informacje, bardzo mi pomogły.
mthecreator
6
Innym rozwiązaniem, które jest nieco czystsze w imo, jest zainicjowanie pustej listy {% set count = [] %}, dodanie pozycji do listy w każdej pętli {% set __ = index.append(1) %}i użycie długości do wyświetlenia indeksu index|length.
eyettea
1
Ponadto, można użyć zrób oświadczenie tak {% do index.append(1) %} Ale trzeba dodać rozbudowa opisane tutaj
AstraSerg
2
Poprawianie czystego rozwiązania @eyettea: Innym rozwiązaniem, które jest nieco czystsze w imo, jest zainicjowanie pustej listy {% set count = [ ] %}, dodanie pozycji do listy w każdej pętli {% set __ = count.append(1) %}i użycie długości do wyświetlenia liczbycount|length
PYB,
14

Oto moje rozwiązanie:

Umieść wszystkie liczniki w słowniku:

{% set counter = {
    'counter1': 0,
    'counter2': 0,
    'etc': 0,
    } %}

Zdefiniuj makro, aby łatwo je zwiększyć:

{% macro increment(dct, key, inc=1)%}
    {% if dct.update({key: dct[key] + inc}) %} {% endif %}
{% endmacro %}

Teraz, gdy chcesz zwiększyć licznik „counter1”, po prostu wykonaj:

{{ increment(counter, 'counter1') }}
Jahid
źródło
Eleganckie rozwiązanie kłopotliwego problemu. Dziękuję Ci!
SevakPrime,
Bardzo dobre! Potrzebowałem skumulowanego indeksu liczącego przechodzącego przez dwie zagnieżdżone pętle for. Działa to świetnie w tym przypadku użycia.
jxramos
2

Ja też walczyłem z tym zachowaniem. Chciałem zmienić klasę div w jinja na podstawie licznika. Byłem zaskoczony, że sposób pythonowy nie działa. Poniższy kod resetował mój licznik po każdej iteracji, więc miałem tylko czerwoną klasę.

{% if sloupec3: %}
    {% set counter = 1 %}
    {% for row in sloupec3: %}
        {% if counter == 3 %}
            {% set counter = 1 %}        
        {% endif %} 

        {% if  counter == 1: %}
           <div class="red"> some red div </div>
        {% endif %} 

        {% if counter == 2: %}
           <div class="gray"> some gray div </div>
        {% endif %} 

        {% set counter = counter + 1 %} 

    {% endfor %}

{% endif %}

Użyłem loop.index w ten sposób i działa:

{% if sloupec3: %}

    {% for row in sloupec3: %} 

        {% if  loop.index % 2 == 1: %}
           <div class="red"> some red div </div>
        {% endif %} 

        {% if loop.index % 2 == 0: %}
           <div class="gray"> some gray div </div>
        {% endif %}  

    {% endfor %}

{% endif %}
TomRavn
źródło
1

jeśli ktoś chce dodać wartość wewnątrz pętli, możesz to wykorzystać w 100%

{% set ftotal= {'total': 0} %} 
{%- for pe in payment_entry -%}
    {% if ftotal.update({'total': ftotal.total + 5}) %}{% endif %} 
{%- endfor -%}

{{ftotal.total}}

wyjście = 5

pratik soni
źródło
0

Zacząłem szukać sposobu, w jaki Django to robi i znalazłem ten post. Może ktoś inny potrzebuje rozwiązania django, który tu przyjechał.

{% for item in item_list %}
    {{ forloop.counter }} {# starting index 1 #}
    {{ forloop.counter0 }} {# starting index 0 #}

    {# do your stuff #}
{% endfor %}

Przeczytaj więcej tutaj: https://docs.djangoproject.com/en/1.11/ref/templates/builtins/

Tuxedo Joe
źródło
2
To Django Template Engine OP poprosił o jinja2
Jahid
Dzięki, że mi pomogło!
Zohab Ali