jinja2 — цикл по словарю

#python #ansible #jinja2

#python #ansible #jinja2

Вопрос:

Я новичок в Jinja2 возможно, мой вопрос неуместен, но я не могу его понять.

Итак, я использую Jinja2 для Ansible задачи в качестве шаблона для создания файла, у меня есть словарь, определенный в файле переменных по умолчанию, например:

 test123:
  testA:
    name: test1
    number: 1
    path: /tmp/test.txt
  testB:
    name: test2
    number: 2
    path: /tmp/test.txt
  

Теперь в моем Jinja2 файле я хочу выполнить цикл по этому словарю и напечатать все, что определено в словаре.

Я пробовал различные примеры, но ничего не получается правильно.

Например:

 {% for item in test123.values() -%}
{{ item.name }}="{{ item.number }}"
{%- endfor %} 
{% for item in test123.testB.values() -%}
    {{ item.name }}="{{ item.number }}"
{%- endfor %} 
  

Сообщение об ошибке:

фатальный: [testserver]: СБОЙ! => {«изменено»: false, «msg»: «AnsibleUndefinedVariable: ‘ansible.parsing.yaml.objects.Объект AnsibleUnicode’ не имеет атрибута ‘name'»}

Я подумал, что, возможно, лучше всего было бы создать для этого цикл while и распечатать все, но поскольку в Jinja2 нет цикла while, я немного запутался, как это сделать.

У кого-нибудь есть идея, как этого добиться? Итак, еще раз цель состоит в том, чтобы напечатать все из словаря в Jinja2 файле.

Заранее благодарю вас

Комментарии:

1. Это не словарь Python .. не уверен насчет Ansible.

2. Какая версия python на целевом хосте?

3. @amanb Я использовал это руководство для создания словаря в ansible: docs.ansible.com/ansible/latest/plugins/lookup/dict.html (в примере вверху вы можете видеть пример) значит, jinja2 ничего не может сделать с этим словарем?

4. @ozlevka версия python на целевом хостинге: Python 2.7.5

Ответ №1:

Приведенное ниже создало бы вывод со всеми именами пользователей в нем

 {% for item in test123.values() %}
name of the user: {{ item.name }}
{% endfor %}
  

Формат вывода:

 name of the user: test1
name of the user: test2
  

Если вам нужно что-то в определенном формате, дайте мне знать желаемый результат

Комментарии:

1. Работает, как ожидалось 🙂 итак, .values() вызывает все значения в dict, верно?

2. ДА. затем вы можете получить доступ к подэлементам с помощью item.name и {{ }} используется для замены переменных в jinja2

Ответ №2:

Одним из вариантов было бы использовать фильтр dict2items. Шаблон ниже

 {% for item in test123|dict2items %}                                                
{{ item }}                                                                          
{% endfor %}

{% for item in test123|dict2items %}
key: {{ item.key }}
value.number: {{ item.value.number }}
value.name: {{ item.value.name }}
value.path: {{ item.value.path }}

{% endfor %}
  

дает

 {'value': {u'path': u'/tmp/test.txt', u'name': u'test1', u'number': 1}, 'key': u'testA'}
{'value': {u'path': u'/tmp/test.txt', u'name': u'test2', u'number': 2}, 'key': u'testB'}

key: testA
value.number: 1
value.name: test1
value.path: /tmp/test.txt

key: testB
value.number: 2
value.name: test2
value.path: /tmp/test.txt
  

Ответ №3:

Это не словарь python. однако, если у вас есть список dicts:

 test123 = [
    {'name':'test1', 'number': 1, 'path': '/tmp/test.txt'},
    {'name':'test2', 'number': 2, 'path': '/tmp/test.txt'},
    ]
  

этот код jinja должен работать:

 {% for item in test123 %}
    {{ item.name }}="{{ item.number }}"
{% endfor %}
  

конечно, вам нужно передать этот dict в вашу функцию рендеринга (вы не публикуете код своего контроллера). Понятия не имею, хорошо ли это применимо к ansible.