¿Cómo incrementar una variable en un bucle for en la plantilla jinja?

83

Me gustaría hacer algo como:

la variable p es de test.py que es una lista ['a', 'b', 'c', 'd']

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

la salida del resultado es:
1 2 3 4

usuario422100
fuente

Respuestas:

157

Podrías usar loop.index:

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

Consulte la documentación del diseñador de plantillas .

En versiones más recientes, debido a las reglas de alcance, lo siguiente no funcionaría:

{% set count = 1 %}
{% for i in p %}
  {{ count }}
  {% set count = count + 1 %}
{% endfor %}
zeekay
fuente
Utilice esta respuesta para resolver el problema del alcance
faruk13
68

Después de 2.10, para resolver el problema del alcance, puede hacer algo como esto:

{% set count = namespace(value=0) %}
{% for i in p %}
  {{ count.value }}
  {% set count.value = count.value + 1 %}
{% endfor %}
Patrick José Pereira
fuente
1
Recibo el error: TemplateSyntaxError en / Listing / Invalid block tag on line 145: 'set', esperado 'endblock'. ¿Olvidó registrarse o cargar esta etiqueta? Activado: {% set count = espacio de nombres (valor = 0)%} ¿Alguna idea de la causa de esto?
Andrew
56

Como dice Jeroen, hay problemas de alcance: si establece 'recuento' fuera del ciclo, no puede modificarlo dentro del ciclo.

Puede vencer este comportamiento utilizando un objeto en lugar de un escalar para 'contar':

{% set count = [1] %}

Ahora puede manipular el recuento dentro de un forloop o incluso un% include%. Así es como incremento el recuento (sí, es tonto pero bueno):

{% if count.append(count.pop() + 1) %}{% endif %} {# increment count by 1 #}
Peter Hollingsworth
fuente
Peter Hollingsworth. Muchas gracias por esa información, me ayudó mucho.
mthecreator
6
Otra solución que es un poco más limpia en mi opinión es inicializar una lista vacía {% set count = [] %}, agregar un elemento a la lista en cada ciclo {% set __ = index.append(1) %}y usar la longitud para mostrar el índice index|length.
eyettea
1
Además, puede usar la declaración do como esta, {% do index.append(1) %} pero debe agregar la extensión descrita aquí
AstraSerg
2
Corregir la solución limpia de @eyettea: otra solución que es un poco más limpia en mi opinión es inicializar una lista vacía {% set count = [ ] %}, agregar un elemento a la lista en cada ciclo {% set __ = count.append(1) %}y usar la longitud para mostrar el recuentocount|length
PYB
14

Esta es mi solución:

Pon todos los contadores en un diccionario:

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

Defina una macro para incrementarlas fácilmente:

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

Ahora, siempre que desee incrementar el contador 'contador1', simplemente haga:

{{ increment(counter, 'counter1') }}
Jahid
fuente
Solución elegante a un problema complicado. ¡Gracias!
SevakPrime
¡Muy bien! Necesitaba un índice de conteo acumulativo que se desplazara por dos bucles for anidados. Esto funciona muy bien para ese caso de uso.
jxramos
2

Yo también estaba luchando con este comportamiento. Quería cambiar la clase div en jinja según el contador. Me sorprendió que la forma pitónica no funcionara. El siguiente código fue restablecer mi contador en cada iteración, por lo que solo tenía la clase roja.

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

Usé loop.index así y funciona:

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

si alguien quiere agregar un valor dentro del ciclo, puede usarlo, está funcionando al 100%

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

{{ftotal.total}}

salida = 5

pratik soni
fuente
0

Vine a buscar la forma de Django de hacer esto y encontré esta publicación. Quizás alguien más necesite la solución de django que venga aquí.

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

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

Lea más aquí: https://docs.djangoproject.com/en/1.11/ref/templates/builtins/

Esmoquin Joe
fuente
2
Eso es Django Template Engine, OP pidió jinja2
Jahid
¡Gracias que me ayudaron!
Zohab Ali