Jinja: Verschachtelte Variablen unterstützen

Erstellt am 7. Dez. 2016  ·  7Kommentare  ·  Quelle: pallets/jinja

Ich habe die Dokumentation und verschiedene Online-Artikel durchsucht und konnte anscheinend keine Erwähnung von verschachtelten Variablen finden, daher eröffne ich eine Funktionsanfrage. Dies könnte vielen Projekten zugute kommen, indem komplexere und automatische Variablenaufrufe ermöglicht werden.

Eine normale Variable kann wie folgt definiert werden:

{{ variable }}

Es wäre nützlich, dynamische Informationen aus einer anderen Variablen zuzulassen, um einen anderen Variablennamen zu füllen.

{{ variable{{ generated_var }} }}

Mein genauer Anwendungsfall ist mit Ansible. Ich erhalte eine Liste von Netzwerkschnittstellengeräten aus einer Variablen (ansible_interfaces). Dann kann ich dies verwenden, um auf die Informationen einer anderen Variablen (z. B. ansible_eth0) zu verweisen. Hier ist ein grundlegender Rahmen dessen, was versucht wird zu erreichen.

{% for interface in ansible_interfaces %}
IPADDR{{ loop.index }}={{ ansible_{{ interface }}.ipv4.address }}
NETMASK{{ loop.index }}={{ ansible_{{ interface }}.ipv4.netmask }}
{% endfor %}

Jinja2 mag das nicht, wenn es rendert, da es sich über die zusätzlichen Klammern beschwert. Was die Umsetzungsmöglichkeiten anbelangt, dachte ich an eine dieser beiden unterschiedlichen Ideen.

(1) Variable Erweiterung zulassen. Dies ist genau das, was ich vorhin gezeigt habe; Variablen können von innen nach außen geparst werden.

(2) Fügen Sie einen Filter hinzu, um einen String in einen Variablennamen umzuwandeln.

{% for interface in ansible_interfaces %}
{% set interface_string="ansible_%s.ipv4.address"|format(interface) %}
IPADDR{{ loop.index }}={{ interface_string|variable }}
NETMASK{{ loop.index }}={{ interface_string|variable }}
{% endfor %}

Hier ist ein grober (nicht funktionierender) Code, der die zweite Idee zeigt.

# vim jinja2/jinja2/filters.py
<strong i="21">@environmentfilter</strong>
def do_variable(environment, s):
    string_to_variable = "{{ %s }}" % s
    return environment.from_string(string_to_variable).render()

Im Idealfall wäre Option 1 in Bezug auf die Nutzung durch den Endbenutzer weniger komplex. Teilen Sie mir Ihre Meinung zu diesem Thema mit. Dies ist das erste Mal, dass ich mir den Code für Jinja2 ansehe, aber ich würde gerne dazu beitragen, wenn Hilfe mit dem Code benötigt wird.

Hilfreichster Kommentar

http://serverfault.com/questions/762079/how-to-loop-through-interface-facts

Klingt so, als könntest du dies tun:

{{ hostvars[inventory_hostname]['ansible_%s' | format(interface)].ipv4.address }}

Ich bin sehr stark :-1: bei Variablennamen. Es ist normalerweise ein Zeichen für eine schlechte Architektur, wenn eine Anwendung keine ordnungsgemäße Liste von Daten bereitstellt, wenn Sie mit einem dynamischen Schlüssel darauf zugreifen oder darüber iterieren müssen. FWIW, ich denke, dieses hostvars Diktat ist etwas hässlich im Vergleich zu einem richtigen Diktat, das Schnittstellennamen zu Schnittstellendaten zuordnet. Ich würde ein Problem mit Ansible eröffnen und vorschlagen, diese Liste in ein Diktat zu ändern. Da das Iterieren über ein Diktat Ihnen seine Schlüssel liefert, ist es möglicherweise nicht einmal abwärtskompatibel, wenn es in ein Diktat geändert wird ...

Alle 7 Kommentare

http://serverfault.com/questions/762079/how-to-loop-through-interface-facts

Klingt so, als könntest du dies tun:

{{ hostvars[inventory_hostname]['ansible_%s' | format(interface)].ipv4.address }}

Ich bin sehr stark :-1: bei Variablennamen. Es ist normalerweise ein Zeichen für eine schlechte Architektur, wenn eine Anwendung keine ordnungsgemäße Liste von Daten bereitstellt, wenn Sie mit einem dynamischen Schlüssel darauf zugreifen oder darüber iterieren müssen. FWIW, ich denke, dieses hostvars Diktat ist etwas hässlich im Vergleich zu einem richtigen Diktat, das Schnittstellennamen zu Schnittstellendaten zuordnet. Ich würde ein Problem mit Ansible eröffnen und vorschlagen, diese Liste in ein Diktat zu ändern. Da das Iterieren über ein Diktat Ihnen seine Schlüssel liefert, ist es möglicherweise nicht einmal abwärtskompatibel, wenn es in ein Diktat geändert wird ...

Ich bin zu 100% damit einverstanden, dass das Inside-Out-Rendering, um Variablen * N Variablennamen zu erhalten, eine SCHLECHTE Idee ist.

Ich bin jedoch hierher gekommen, um nach einer Lösung für die Verschachtelung von Outside-In-Rendern zu suchen nested_render Filters von Vorteil oder schädlich, da er die Leute wahrscheinlich verwirren könnte?

Verschachtelte Variablen würden ein Problem mit WTForms lösen, in dem ein Konstrukt wie
{{ form.playername(value="{{ currentname }}") }}
wäre viel klarer als jede andere Lösung, die ich gefunden habe.

{{ form.playername(value=currentname) }} tut es. aber zur Info, Sie sollten die aktuellen Daten an den Formularkonstruktor übergeben und sich in den Vorlagen überhaupt nicht damit beschäftigen

Ach, so einfach ist das! Am Ende habe ich Javascript verwendet, um den Wert aus der Variablen currentname zu setzen. Wenn ich den Standardwert im Formularobjekt im Python-Code festlege, wird er nicht aktualisiert.

Gehen Sie in #pocoo im IRC vorbei und pingen Sie mich dort an (es ist hier sehr offtopic) und ich kann Ihnen sagen, wie man es richtig macht.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen