Jinja: Soporta variables anidadas

Creado en 7 dic. 2016  ·  7Comentarios  ·  Fuente: pallets/jinja

He estado buscando en documentación y varios artículos en línea y parece que no pude encontrar ninguna mención de tener variables anidadas, así que estoy abriendo una solicitud de función. Esto podría ayudar a beneficiar muchos proyectos al permitir llamadas variables más complejas y automáticas.

Una variable normal se puede definir así:

{{ variable }}

Sería útil permitir que la información dinámica de otra variable se utilice para completar el nombre de otra variable.

{{ variable{{ generated_var }} }}

Mi caso de uso exacto es con Ansible. Estoy tomando una lista de dispositivos de interfaz de red de una variable (ansible_interfaces). Entonces puedo usar esto para hacer referencia a la información de otra variable (ansible_eth0, por ejemplo). Aquí hay un marco básico de lo que se intenta lograr.

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

A Jinja2 no le gusta eso cuando se renderiza, ya que se queja de los corchetes adicionales que existen. Para las opciones de cómo implementar esto, estaba pensando en la línea de una de estas dos ideas diferentes.

(1) Permitir expansión variable. Esto es exactamente lo que estaba mostrando antes; permitiendo analizar las variables de adentro hacia afuera.

(2) Agregue un filtro para convertir una cadena en un nombre de variable.

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

Aquí hay un código aproximado (que no funciona) que muestra la segunda idea.

# 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()

Idealmente, la opción 1 sería menos compleja en términos de uso por parte del usuario final. Déjame saber tu opinión al respecto. Esta es la primera vez que miro el código de Jinja2, pero me encantaría contribuir si se necesita ayuda con el código.

Comentario más útil

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

Parece que puedes hacer esto:

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

Soy muy fuerte: -1: en nombres de variables. Por lo general, es un signo de mala arquitectura si una aplicación no proporciona un diccionario / lista de datos adecuada si necesita acceder a ella mediante una clave dinámica o iterar sobre ella. FWIW, creo que este hostvars dict es algo feo comparado con un dict apropiado para asignar nombres de interfaz a datos de interfaz. Abriría un problema con Ansible, sugiriendo cambiar esa lista a un dict. Dado que la iteración sobre un dict le da sus claves, es posible que ni siquiera sea incompatible con las versiones anteriores si lo cambiaran a un dict ...

Todos 7 comentarios

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

Parece que puedes hacer esto:

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

Soy muy fuerte: -1: en nombres de variables. Por lo general, es un signo de mala arquitectura si una aplicación no proporciona un diccionario / lista de datos adecuada si necesita acceder a ella mediante una clave dinámica o iterar sobre ella. FWIW, creo que este hostvars dict es algo feo comparado con un dict apropiado para asignar nombres de interfaz a datos de interfaz. Abriría un problema con Ansible, sugiriendo cambiar esa lista a un dict. Dado que la iteración sobre un dict le da sus claves, es posible que ni siquiera sea incompatible con las versiones anteriores si lo cambiaran a un dict ...

Estoy 100% de acuerdo en que la representación de adentro hacia afuera para obtener la variable * N nombres de variable es una MALA idea.

Sin embargo, llegué aquí buscando una solución para el anidamiento de renderizado de afuera hacia adentro y terminé explorando la solución yo mismo. ¿Existe apoyo para tal cosa? ¿Sería beneficioso o perjudicial agregar un filtro nested_render en el sentido de que probablemente confundiría a las personas?

Las variables anidadas resolverían un problema con WTForms, en el que una construcción como
{{ form.playername(value="{{ currentname }}") }}
sería mucho más claro que cualquier otra solución que haya encontrado.

{{ form.playername(value=currentname) }} hace. pero para su información, debe pasar los datos actuales al constructor del formulario y no molestarse con ellos en las plantillas

¡Ah, es así de simple! Terminé usando Javascript para establecer el valor de la variable currentname. Cuando establezco el valor predeterminado en el objeto de formulario en el código de Python, no se actualiza.

Pase en #pocoo en IRC y haga ping allí (es muy diferente del tema aquí) y puedo decirle cómo hacerlo correctamente.

¿Fue útil esta página
0 / 5 - 0 calificaciones