python - 使用 jinja2 访问嵌套的 YAML 映射

标签 python yaml jinja2 pyyaml

我最近开始使用 YAML 和 jinja2。我无法理解为什么我需要在 jinja2 模板中引用我的 YAML 映射的整个结构。

我有以下 YAML 文件

---
PROVIDERS:
    PROV1:
        int: ge-0/1/1
        ipv4: 10.0.1.1/30
    PROV2:
        int: ge-0/1/2
        ipv4: 10.0.1.2/30

这是我的 jinja2 模板

{%- for provider in PROVIDERS %}
    {{ provider }}
    {{ PROVIDERS[provider].int }}   <-- why not provider.int
    {{ PROVIDERS[provider].ipv4 }}  <-- why not provider.ipv4
{%- endfor %}

用 pyyaml 解析给了我(预期的)输出

PROV2
ge-0/1/2
10.0.1.2/30
PROV1
ge-0/1/1
10.0.1.1/30

但是为什么我必须使用 PROVIDERS[provider].intprovider.int 不起作用。

另外,我想知道我是否可以将其设为映射列表而不是嵌套映射:

---
PROVIDERS:
    - PROV1:
        int: ge-0/1/1
        ipv4: 10.0.1.1/30
    - PROV2:
        int: ge-0/1/2
        ipv4: 10.0.1.2/30

我已尝试这样做,但 jinja2 模板不再产生所需的输出。

最佳答案

这里有两点需要考虑:

  1. 您的 YAML 文档构建了哪种 Python 数据结构?
  2. 您的模板如何引用该数据结构的元素?

回答点 1 很简单:

>>> import yaml
>>> from pprint import pprint
>>> p1 = yaml.load("""
... ---
... PROVIDERS:
...     PROV1:
...         int: ge-0/1/1
...         ipv4: 10.0.1.1/30
...     PROV2:
...         int: ge-0/1/2
...         ipv4: 10.0.1.2/30
... """)
>>> pprint(p1)
{'PROVIDERS': {'PROV1': {'int': 'ge-0/1/1', 'ipv4': '10.0.1.1/30'},
               'PROV2': {'int': 'ge-0/1/2', 'ipv4': '10.0.1.2/30'}}}

您有一个包含单个项目的字典,其键为 'PROVIDERS',其值为键为 'PROV1''PROV2 的字典',每个值都是一个进一步的字典。这是一个比您需要的嵌套更深的结构(稍后会详细介绍),但现在我们可以看到您的数据结构,我们可以弄清楚您的模板发生了什么。

这一行:

{%- for provider in PROVIDERS %}

遍历 PROVIDERSkeys(根据您的输出,这显然是二级嵌套字典,它是键 'PROVIDERS 的值' 在你的顶级字典中)。由于您要迭代的是键,因此您需要使用这些键来获取关联的值:

{{ PROVIDERS[provider].int }}
{{ PROVIDERS[provider].ipv4 }}

一个更直接的 YAML 文档对于您的目的是这样的:

---
- id: PROV1
  int: ge-0/1/1
  ipv4: 10.0.1.1/30
- id: PROV2
  int: ge-0/1/2
  ipv4: 10.0.1.2/30

请注意,我们已经放弃了冗余的单项映射,并将映射的二级映射替换为映射列表。同样,我们可以检查:

>>> p2 = yaml.load("""
... ---
... - id: PROV1
...   int: ge-0/1/1
...   ipv4: 10.0.1.1/30
... - id: PROV2
...   int: ge-0/1/2
...   ipv4: 10.0.1.2/30
... """)
>>> pprint(p2)
[{'int': 'ge-0/1/1', 'ipv4': '10.0.1.1/30', 'id': 'PROV1'},
 {'int': 'ge-0/1/2', 'ipv4': '10.0.1.2/30', 'id': 'PROV2'}]

以下是您的模板如何使用此数据结构:

{%- for provider in PROVIDERS %}
    {{ provider.id }}
    {{ provider.int }}
    {{ provider.ipv4 }}
{%- endfor %}

显然,您需要修改为模板提供 PROVIDERS 的代码,因为它现在是整个 YAML 文档所代表的顶级列表,而不是嵌套在其中的字典。

关于python - 使用 jinja2 访问嵌套的 YAML 映射,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27723128/

相关文章:

python - 在 matplotlib 中绘制共享 x 轴的两个图

syntax - 如何正确拥有多行 yaml 字符串?

python - Jinja2动态变量构建

for-loop - Jinja2 同一个 for 循环中的多个变量

python - 如果我们在单个 jinja 模板中有多个宏。如何在Python中渲染其中的特定宏

python - 为什么 Python 中的(守护进程)线程在使用进程池时会出现这种行为?

python - 使用列表输出而不是元组进行压缩

python - Ansible - 如何在不同键的 yaml 中使用 selectattr

kubernetes - helm chart : Include multiple lines from values. yaml 到 configmap

ruby-on-rails - rake db:create“未知的无法解析YAML” sqlite3