Я бы сначала преобразовал ваши словари в список списков с более простой структурой таблиц с необходимыми пустыми ячейками.
def dicts_to_lists(data):
""" Convert data stored as lists within dicts within a dict, to a simple
list of lists """
r = []
for user, projects in data.items():
user_cell = user
for project, branches in projects.items():
project_cell = project
for branch in branches:
r.append([user_cell, project_cell, branch])
user_cell = ""
project_cell = ""
return r
Словари не упорядочены в Python, поэтому функция может выводить 'project_B'до «проекта_А».Если вам нужно сохранить тот же порядок, используйте OrderedDict для хранения данных.В противном случае вы можете написать более сложную функцию, которая сортирует ключи в алфавитном порядке.
Затем вы можете использовать язык шаблонов или написать короткую универсальную функцию для преобразования любого списка списков в HTML-таблицу:
def lists_to_html(data, has_header=True):
html = "<table>"
for i, row in enumerate(data):
if has_header and i == 0:
tag = "th"
else:
tag = "td"
tds = ''.join("<{}>{}</{}>".format(tag, cell, tag) for cell in row)
html += "<tr>{}</tr>".format(tds)
html += "</table>"
return html
data = {
'user_one': {'project_a': ['branch_1', 'branch_2'],
'project_b': ['branch_1']},
'user_two': {'project_x': ['branch_x1', 'branch_b'] }
}
table_cells = dicts_to_lists(data)
table_cells = [["User", "Project", "Branch"]] + table_cells
print (lists_to_html(table_cells))
Эта функция lists_to_html
может быть выполнена с использованием шаблона jinja2, например:
def lists_to_html(data):
template = """
<table><tr><th>User</th><th>Project</th><th>Branch</th></tr>
{% for r in data %}
<tr><td>{{ r.author }}</td><td<{{ r.project }}</td><td>{{ r.branch }}</td></tr>
{% endfor %}</table>"""
return jinja2.Environment().from_string(template).render(data=data)
В качестве альтернативы, вы можете заменить обе функции на несколько более сложный шаблон jinja2:
template = """
<table>
<tr><th>User</th><th>Project</th><th>Branch</th></tr>
{% for author, projects in data.items() %}
{% for project, branches in projects.items() %}
{% set project_loop = loop %}
{% for branch in branches %}
<tr><td>{% if project_loop.first and loop.first %}{{ author }}{% endif %}</td>
<td>{% if loop.first %}{{ project }}{% endif %}</td>
<td>{{ branch }}</td></tr>
{% endfor %}
{% endfor %}
{% endfor %}
</table>
"""
print jinja2.Environment().from_string(template).render(data=data)