2014-12-31 1 views
4

Я недавно начал использовать YAML и jinja2. У меня возникли проблемы с пониманием того, почему мне нужно ссылаться на всю структуру моего сопоставления YAML в шаблоне jinja2.Доступ к вложенным сопоставлениям YAML с jinja2

У меня есть следующий файл с 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 больше не произвел желаемого выхода.

ответ

4

Есть две вещи, чтобы рассмотреть здесь:

  1. Какая структура данных Python конструируется из вашего YAML документа?
  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, а не словарь, вложенный в него.