Создание таблицы HTML с Python с несколькими столбцами для конкретной строки - PullRequest
0 голосов
/ 12 октября 2018

Я написал этот код:

tr = ""
for author, projects in data.iteritems():
    tr + = "<tr><td>{}</td>".format(author)
    for project, branches in projects.iteritems():
        tr += "<td>{}</td>".format(project)
        for branch in branches:
            tr += "<td>{}</td>".format(branch)
    tr += </td></tr>
end = "</table>"

У меня есть этот набор данных

{
'user_one': {'project_a': ['branch_1', 'branch_2'],
          'project_b': ['branch_1']},
'user_two': {'project_x': ['branch_x1', 'branch_b'] }
}

Я хочу напечатать таблицу, как показано ниже:

+-------------------------------------------+
|    User    |    Project    |    Branch    |
+------------+---------------+--------------+
|  user_one  |   project_a   |   branch_1   |
+------------+---------------+--------------+
|            |               |   branch_2   |
+------------+---------------+--------------+
|            |   project_b   |   branch_1   |
+------------+---------------+--------------+
|  user_two  |  project_x    |   branch_x1  |
+------------+---------------+--------------+
|            |               |   branch_b   |
+------------+---------------+--------------+

, если она однаПроект работает нормально, но когда речь идет о нескольких проектах, это не так.Я могу получить результат, используя PrettyTable, но я хочу, чтобы project_a, _b, _x и т. Д. Были гиперссылками.Я не могу добиться этого при использовании PrettyTable, поэтому я начал писать свой собственный генератор HTML на основе данных.

Ответы [ 3 ]

0 голосов
/ 12 октября 2018

Помимо тривиального HTML (таблица может и не быть) Я рекомендую использовать библиотеку шаблонов .

Я бы выбрал Jinja2 .Его синтаксис довольно прост и интуитивен (если вы видели какой-либо другой язык шаблонов), он хорошо документирован , и он довольно популярен (= больше поддержки SO ).

Пример для рендеринга таблицы.

<table class="table table-striped">
    <thead><tr>
        <th>One</th>
        <th>Two</th>
        <th>Three</th>
        <th>Four</th>
    </tr></thead>
    <tbody>
    {% for row in tabular_data %}
    <tr>
        <td>{{ row.one }}</td>
        <td>{{ row.two }}</td>
        <td>{{ row.three }}</td>
        <td>{{ row.four }}</td>
    </tr>
    {% endfor %}
    </tbody>
</table>

Если вы используете веб-фреймворк, он, вероятно, поддерживается сразу после установки, если нет, то рендеринг - это всего лишь несколько строк:

from jinja2 import Environment, FileSystemLoader  # pip install Jinja2

env = Environment(loader=FileSystemLoader("/path/to/templates/folder")
template = env.get_template("TableTemplate.html")  # the template file name
html = template.render(**context_data)

Где context_dataсловарь с необходимыми данными.В приведенном выше примере ожидается поле tabular_data, содержащее массив объектов (или словарей) со свойствами one, two, ...:

context_data = {
    # Row = namedtuple("Row", ["one", "two", "three", "four"])
    'tabular_data': [             
        Row(1, 2, 3, 4), 
        Row("a", "b", "c", "d"),
        ..., 
    ]
}
0 голосов
/ 12 октября 2018

Я бы сначала преобразовал ваши словари в список списков с более простой структурой таблиц с необходимыми пустыми ячейками.

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)
0 голосов
/ 12 октября 2018

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

table = "<table border=1 ><tr><th>user</th><th>Project</th><th>Branch</th></tr>"
tr = ""
td_1 = ""
td_2 = ""
for author, projects in data.iteritems():
    # reset the value for new input.
    td_1 = ""
    td_2 = ""
    for project, branches in projects.iteritems():
        td_1 += "{}<hr>".format(project)
        for branch in branches:
            td_2 += "{}<hr>".format(branch)
    tr += "<tr><td valign='top'>{}</td><td valign='top'>{}</td><td valign='top'>{}</td></tr>".format(author, td_1, td_2)

end = "</table>"
table = table + tr + end

Это делает

enter image description here

Вы можете использовать CSS и настроить внешний вид .. Надеюсь, это поможет!

...