使用jinja2访问嵌套YAML映射

2024-06-16 08:30:27 发布

您现在位置:Python中文网/ 问答频道 /正文

我最近开始使用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模板不再产生所需的输出。


Tags: 文件模板jinja2yamlfornotprovider结构
1条回答
网友
1楼 · 发布于 2024-06-16 08:30:27

这里有两件事要考虑:

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

迭代PROVIDERS(根据您的输出,这显然是二级嵌套字典,是顶级字典中键'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文档表示的顶级列表,而不是嵌套在其中的字典。

相关问题 更多 >