Итерация вложенного dict в шаблоне mako

У меня есть следующий дикт:

{"name1":{"text":"my text 1", "status":"my status"}, "name2":{"text":"my text 2", "status":"my status"}}

Используя шаблон Mako, я хочу создать HTML-таблицу. Я попробовал следующее:

Фрагмент Python:

test = {"name1":{"text":"my text 1", "status":"my status"}, "name2":{"text":"my text 2", "status":"my status"}}
mytemplate = Template(filename='template/index.mako')
return mytemplate.render(data=test)

Мако фрагмент:

% for key, val in data.iteritems():
    <tr>
        <td>${loop.index + 1}</td>
        <td>${key}</td>
        % for tkey, tval in val.iteritems():
            <td>${tkey}</td>
            <td>${tval}</td>
        % endfor
    </tr>
% endfor

Приведенные выше фрагменты вызывают ошибку (объект 'str' не имеет атрибута 'iteritems').

Как правильно перебирать вложенные диктовки?

Спасибо

1 ответ

Это странно сложно сделать. Недавно я пытался сделать что-то очень похожее, нашел этот пост, и мне было грустно видеть, что на него не было никаких ответов.

Вы просили "правильный" способ, и я думаю, что итерации по элементам будут наиболее питонским способом; но я также не смог заставить это работать. Я смог заставить работать рекурсивный парсер (с дополнительным бонусом, который будет обрабатывать n уровней вложенности).

Я получил это на работу:

from mako.template import Template

template = '''
${handleLevel(pages)}
<%def name="handleLevel(level, depth=0)">
    % if isinstance(level, dict):
            % for item in level:
                % if isinstance(level[item], dict):
                    <!-- print this item for this level -->
                        ${handleLevel(level[item], depth+1)}
                    <!-- end this level (close div or anything that should contain next level -->
                % else:
                    <!-- handle bottom level (linke, or div, etc.) -->
                    ${item}
                    <!-- close any elements for bottom level not already closed -->
                % endif
            % endfor
    % endif
</%def>
'''

nested = {
    'A': {'B': 'C'},
    'D': 'E',
}
page = Template(template).render(pages=nested)
print(page)

Если вы знаете, что у вас когда-либо будет только один уровень вложенности, вы можете просто выполнить цикл for, например:

from __future__ import print_function
from mako.template import Template

template = '''
% for key in data:
    <tr>
        <td>${loop.index + 1}</td>
        <td>${key}</td>
        % for secondKey in data[key]:
            <td>${secondKey}</td>
            <td>${data[key][secondKey]}</td>
        % endfor
    </tr>
% endfor
'''

test = {"name1":{"text":"my text 1", "status":"my status"}, "name2":{"text":"my text 2", "status":"my status"}}
page = Template(template).render(data=test)
print(page)

(проверено в Python3 и 2)

Хотя теперь, когда я немного поиграл с этим, ваш код отлично работает для меня в Python 2.7.15 и mako версии 1.0.7 .,,

Другие вопросы по тегам