【问题标题】:Creating a HTML table with Python with multiple columns for a specific row使用 Python 为特定行创建一个包含多列的 HTML 表
【发布时间】:2019-03-17 12:47:58
【问题描述】:

我写了这段代码:

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 生成器。

【问题讨论】:

标签: python html-table tablecolumn


【解决方案1】:

除了简单的 HTML(可能不是表格),我建议使用 template library

我会选择Jinja2。它的语法非常简单直观(如果您见过任何其他模板语言),它是well documented,并且非常流行(=more SO support)。

呈现表格的示例。

<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>

如果您使用的是 Web 框架,它可能是开箱即用的,如果不是,则只需几行即可呈现它:

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 字段,其中包含一个具有属性 onetwo、...的对象(或字典)数组:

context_data = {
    # Row = namedtuple("Row", ["one", "two", "three", "four"])
    'tabular_data': [             
        Row(1, 2, 3, 4), 
        Row("a", "b", "c", "d"),
        ..., 
    ]
}

【讨论】:

    【解决方案2】:

    如果您只需要渲染表格,为什么要依赖整个包!

    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
    

    这个渲染

    您可以使用 css 并自定义外观 .. 我希望这会有所帮助!

    【讨论】:

      【解决方案3】:

      我会首先将您的字典转换为具有更简单表结构的列表列表,并根据需要使用空单元格。

      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_A”之前输出“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)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-09-21
        • 1970-01-01
        • 2022-01-10
        • 2023-03-11
        • 2015-05-28
        • 2015-05-18
        • 1970-01-01
        相关资源
        最近更新 更多