Jinja: 支持嵌套变量

创建于 2016-12-07  ·  7评论  ·  资料来源: pallets/jinja

我一直在搜索文档和各种在线文章,似乎找不到任何提及嵌套变量的内容,因此我提出了一个功能请求。 这可以通过允许更复杂和自动的变量调用来帮助许多项目受益。

一个普通变量可以这样定义:

{{ variable }}

允许使用来自另一个变量的动态信息来填充另一个变量名称会很有用。

{{ variable{{ generated_var }} }}

我的确切用例是 Ansible。 我正在从一个变量 (ansible_interfaces) 中获取网络接口设备列表。 然后我可以使用它来引用来自另一个变量(例如 ansible_eth0)的信息。 这是试图完成的基本框架。

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

Jinja2 在渲染时不喜欢这样,因为它抱怨存在额外的括号。 对于如何实现这一点的选项,我正在考虑这两种不同想法之一。

(1) 允许变量扩展。 这正是我之前展示的; 允许从内到外解析变量。

(2) 添加过滤器,将字符串转换为变量名。

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

这是一些粗略的(非工作)代码,显示了第二个想法。

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

理想情况下,选项 1 在最终用户使用方面不会那么复杂。 让我知道你对此事的看法。 这是我第一次研究 Jinja2 的代码,但如果代码需要任何帮助,我很乐意回馈。

最有用的评论

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

听起来你可以这样做:

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

我很强大:-1: 在变量变量名上。 如果您需要通过动态键访问它或对其进行迭代,如果应用程序没有提供正确的数据字典/列表,这通常是架构不良的标志。 FWIW,我认为这个hostvars dict 与将接口名称映射到接口数据的正确 dict 相比有些丑陋。 我会用 Ansible 打开一个问题,建议将该列表更改为 dict。 由于迭代 dict 会产生它的键,如果他们将其更改为 dict ,它甚至可能不会向后不兼容......

所有7条评论

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

听起来你可以这样做:

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

我很强大:-1: 在变量变量名上。 如果您需要通过动态键访问它或对其进行迭代,如果应用程序没有提供正确的数据字典/列表,这通常是架构不良的标志。 FWIW,我认为这个hostvars dict 与将接口名称映射到接口数据的正确 dict 相比有些丑陋。 我会用 Ansible 打开一个问题,建议将该列表更改为 dict。 由于迭代 dict 会产生它的键,如果他们将其更改为 dict ,它甚至可能不会向后不兼容......

我 100% 同意由内而外渲染以获取变量 * N 变量名称是一个主意。

但是,我来到这里是为了寻找由外向内渲染嵌套的解决方案,并最终自己探索了该解决方案。 有没有支持这样的事情? 添加nested_render过滤器是有益还是有害,因为它可能会使人们感到困惑?

嵌套变量将解决 WTForms 的问题,其中的构造类似于
{{ form.playername(value="{{ currentname }}") }}
会比我找到的任何其他解决方案更清晰。

{{ form.playername(value=currentname) }}做到了。 但是仅供参考,您应该将当前数据传递给表单构造函数,而根本不要在模板中使用它

啊,就是这么简单! 我最终使用 Javascript 来设置 currentname 变量的值。 当我在 Python 代码的表单对象中设置默认值时,它不会更新。

在 IRC 上输入#pocoo在那里 ping 我(这里非常离题),我可以告诉你如何正确地做到这一点。

此页面是否有帮助?
0 / 5 - 0 等级