Jinja2: Verander de waarde van een variabele in een loop

Ik wil het wijzigen van de waarde van de variabele is gedeclareerd buiten de loop binnen een loop. Maar altijd aan het veranderen, het houdt de oorspronkelijke waarde buiten de lus.

{% set foo = False %}

{% for item in items %}
  {% set foo = True %}
  {% if foo %} Ok(1)! {% endif %}
{% endfor %}

{% if foo %} Ok(2)! {% endif %}

Dit maakt:

Ok(1)!

Dus de enige (slechte) oplossing hebben gevonden tot nu toe was dit:

{% set foo = [] %}

{% for item in items %}
  {% if foo.append(True) %} {% endif %}
  {% if foo %} Ok(1)! {% endif %}
{% endfor %}

{% if foo %} Ok(2)! {% endif %}

Dit maakt:

Ok(1)!
Ok(2)!

Maar, het is heel erg lelijk! Is er een andere, meer elegante oplossing?

  • Ik denk niet dat er een andere manier. Misschien kunt u herstructurering van de code, zodat u niet nodig om de variabele.
  • +1 voor de vraag, omdat het antwoord werd voor mij 🙂
  • Cabus: goede vraag. Dit moet waarschijnlijk worden ingedeeld onder Jinja Annoyances
  • Ik denk dat dit een vraag is gedupliceerd in: stackoverflow.com/questions/7537439/… en stackoverflow.com/questions/4870346/… (net starten, kan het niet de vlag van de vraag) kunt U gebruik maken van Pashka de aanpak, en voeg jinja2.ext.do om het schoon te maken een beetje
  • Ik vond deze code is de enige manier om een oplossing te construeren dat ik niet in staat was om te gebruiken in zout+jinja: somelist|kaart(formaat)|join

 

3 Replies
  1. 60

    Probeer ook dictionary-based benadering. Het lijkt minder lelijk.

    {% set vars = {'foo': False} %}
    
    {% for item in items %}
      {% if vars.update({'foo': True}) %} {% endif %}
      {% if vars.foo %} Ok(1)! {% endif %}
    {% endfor %}
    
    {% if vars.foo %} Ok(2)! {% endif %}

    Dit ook maakt:

    Ok(1)!
    Ok(2)!
    • Nog steeds lelijk, maar het werkt. Ik ben heel verbaasd is er geen Pythonic manier om dit te doen met jinja2.
    • Zeker een beetje schoner, vooral als u meer dan één variabele
    • TLDR, doet set vars gewoon niet werken in een for-lus?
    • Oplossingen lijken te zijn in het werk: github.com/pallets/jinja/pull/684; github.com/pallets/jinja/pull/676
    • lijkt het. Ik heb gehoord van veel mensen lof python. Ze zijn gewoon koken met water.
  2. 31

    zoals vermeld in de documentatie:

    Houd er rekening mee dat de opdrachten in loops zal worden gewist bij het einde van
    de iteratie en kan niet overleven in de loop van het toepassingsgebied.

    maar als van versie 2.10 kunt u gebruik maken van naamruimten:

        {% set ns = namespace(foo=false) %}      
        {% for item in items %}
          {% set ns.foo = True %}
          {% if ns.foo %} Ok(1)! {% endif %}
        {% endfor %}
    
        {% if ns.foo %} Ok(2)! {% endif %}
    • Waar u zeggen namespace(foo=false) is de kleine letter f in een Valse jinja2 colloquialism of bedoelt u Valse, zoals python vereist voor de waarden van booleaans?
    • de kleine onwaar is een onderdeel van jinja verdrag: “The special constants true, false, and none are indeed lowercase. Because that caused confusion in the past, (True used to expand to an undefined variable that was considered false), all three can now also be written in title case (True, False, and None). However, for consistency, (all Jinja identifiers are lowercase) you should use the lowercase versions.
  3. 0

    U zou dit kunnen doen voor het opschonen van de template-code

    {% for item in items %}
      {{ set_foo_is_true(local_vars) }}
      {% if local_vars.foo %} Ok(1)! {% endif %}
    {% endfor %}
    {% if local_vars.foo %} Ok(2)! {% endif %}

    En in de server code gebruiken

    items = ['item1', 'item2', 'item3']
    #---------------------------------------------
    local_vars = { 'foo': False }
    def set_foo_is_true(local_vars):
      local_vars['foo'] = True
      return ''
    env.globals['set_foo_is_true'] = set_foo_is_true    
    #---------------------------------------------
    return env.get_template('template.html').render(items=items, local_vars=local_vars)

    Deze kunnen worden gegeneraliseerd naar de volgende

    {{ set_local_var(local_vars, "foo", False) }}
    {% for item in items %}
      {{ set_local_var(local_vars, "foo", True) }}
      {% if local_vars.foo %} Ok(1)! {% endif %}
    {% endfor %}
    {% if local_vars.foo %} Ok(2)! {% endif %}

    En in de server code gebruiken

    items = ['item1', 'item2', 'item3']
    #---------------------------------------------
    local_vars = { 'foo': False }
    def set_local_var(local_vars, name, value):
      local_vars[name] = value
      return ''
    env.globals['set_local_var'] = set_local_var
    #---------------------------------------------
    return env.get_template('template.html').render(items=items, local_vars=local_vars)

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *