我有一个python dict,其中每个键对应一个标题,与每个标题关联的列表包含任意数量的值:
data = {
"heading1": ['h1-val1', 'h1-val2', 'h1-val3', ],
"heading2": ['h2-val1', ],
"heading3": ['h3-val1', 'h3-val2', 'h3-val3', 'h3-val4', ],
}
我需要在Django模板中将其渲染为表格,其中值在每个标题下方垂直列出,任何缺失值都呈现为空表格单元格:
<table>
<thead>
<tr>
<th>heading1</th>
<th>heading2</th>
<th>heading3</th>
</tr>
</thead>
<tbody>
<tr>
<td>h1-val1</td>
<td>h2-val1</td>
<td>h3-val1</td>
</tr>
<tr>
<td>h1-val2</td>
<td></td>
<td>h3-val2</td>
</tr>
<tr>
<td>h1-val3</td>
<td></td>
<td>h3-val3</td>
</tr>
<tr>
<td></td>
<td></td>
<td>h3-val4</td>
</tr>
</tbody>
</table>
实现这一目标的最佳方式是什么?
我的第一个倾向是将原始字典重新排列成2D矩阵,然后将其传递到模板中。我确信我不是第一个遇到这种问题的人,我很好奇其他人是如何解决这个问题的。
更新:仅供参考,这是我对此问题的原始解决方案(我对此并不满意)。
# Using the data dict from the question:
size = max(len(data['heading1']), len(data['heading2']), len(data['heading3']))
matrix = [[None, None, None] for i in range(size)] # initialize an empty matrix
# manually copy the data into the appropriate column :(
i = 0
for item in data['heading1']:
matrix[i][0] = item
i += 1
i = 0
for item in data['heading2']:
matrix[i][1] = item
i += 1
i = 0
for item in data['heading3']:
matrix[i][2] = item
i += 1
然后我将矩阵传递到模板中,如下所示:
<table>
<thead><tr>
<th>heading1</th>
<th>heading2</th>
<th>heading3</th>
</tr></thead>
<tbody>
{% for row in matrix %}
<tr>
{% for col in row %}
<td>{% if col %}{{ col }}{% else %} {% endif %}</td>
{% endfor %}
</tr>
{% endfor %}
</tbody>
</table>
答案 0 :(得分:5)
如果我们稍微更改一下游戏,那么实际上很容易转过来(只要你的列表没有填充......)
from django.template import Context, Template
data = {
"heading1": ['h1-val1', 'h1-val2', 'h1-val3', ],
"heading2": ['h2-val1', ],
"heading3": ['h3-val1', 'h3-val2', 'h3-val3', 'h3-val4', ],
}
# we'll need to split the headings from the data
# rather than using keys() I'm just hard coding so I can control the order
headings = ["heading1", "heading2", "heading3"]
columns = [data[heading] for heading in headings]
# get the length of the longest column
max_len = len(max(columns, key=len))
for col in columns:
# padding the short columns with None
col += [None,] * (max_len - len(col))
# Then rotate the structure...
rows = [[col[i] for col in columns] for i in range(max_len)]
dj_template ="""
<table>
{# headings #}
<tr>
{% for heading in headings %}
<th>{{ heading }}</th>
{% endfor %}
</tr>
{# data #}
{% for row in data %}
<tr>
{% for val in row %}
<td>{{ val|default:'' }}</td>
{% endfor %}
</tr>
{% endfor %}
</table>
"""
# finally, the code I used to render the template:
tmpl = Template(dj_template)
tmpl.render(Context(dict(data=rows, headings=headings)))
对我来说,这会产生以下内容(空白行被删除):
<table>
<tr>
<th>heading1</th>
<th>heading2</th>
<th>heading3</th>
</tr>
<tr>
<td>h1-val1</td>
<td>h2-val1</td>
<td>h3-val1</td>
</tr>
<tr>
<td>h1-val2</td>
<td></td>
<td>h3-val2</td>
</tr>
<tr>
<td>h1-val3</td>
<td></td>
<td>h3-val3</td>
</tr>
<tr>
<td></td>
<td></td>
<td>h3-val4</td>
</tr>
</table>
答案 1 :(得分:2)
Kenneth Reitz建议你也可以使用tablib来解决这个问题,所以我想我也会在这里加入:
import tablib
d = tablib.Dataset()
d.append_col(['h1-val1', 'h1-val2', 'h1-val3', ''], header="heading1")
d.append_col(['h2-val1', 'h2-val2', '', ''], header="heading2")
d.append_col(['h3-val1', 'h3-val2', 'h3-val3', 'h3-val4', ], header="heading3")
d.headers = ['heading1', 'heading2', 'heading3']
这会转储数据集中的所有相关数据,然后您可以在模板中使用以下内容进行渲染:
{{ d.html }}
哪个会生成如下所示的html:
<table>
<thead>
<tr><th>heading1</th>
<th>heading2</th>
<th>heading3</th></tr>
</thead>
<tr><td>h1-val1</td>
<td>h2-val1</td>
<td>h3-val1</td></tr>
<tr><td>h1-val2</td>
<td>h2-val2</td>
<td>h3-val2</td></tr>
<tr><td>h1-val3</td>
<td></td>
<td>h3-val3</td></tr>
<tr><td></td>
<td></td>
<td>h3-val4</td></tr>
</table>
答案 2 :(得分:0)
尝试以下代码。请注意,由于您对数据使用关联数组,因此无法保证标题的显示顺序。
print "<table>"
print "<thead><tr>"
order = []
for k in data.keys():
print "<td>" + k + "</td>"
order.append(k)
print "</tr></thead>"
print "<tbody>"
for k in order:
print "<tr>"
for v in data[k]:
print "<td>" + v + "</td>"
print "</tr>"
print "</tbody>"
print "</table>"