我最近开始使用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].int
? provider.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模板不再产生所需的输出。
答案 0 :(得分:4)
这里有两件事需要考虑:
回答第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文档所代表的顶级列表,而不是嵌套在里面的字典它