2011-07-30 40 views
5

我得到了與每個按鍵對應一個標題Python字典,並與每一個標題相關聯的列表包含的值任意數量的:如何使Python字典與豎列的HTML表格

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> 

什麼來實現的最佳途徑這個?

我的第一個傾向是將原始字典重新排列成二維矩陣,並將其傳遞到模板中。但我確信我不是第一個遇到這種問題的人,而且我很好奇別人怎麼解決這個問題。

更新:僅供參考,這是我對這個問題的原始解決方案(我不是很滿意)。

# 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 %}&nbsp;{% endif %}</td> 
    {% endfor %} 
    </tr> 
{% endfor %} 
</tbody> 
</table> 

回答

4

如果我們改變了遊戲一點點,它實際上是一個捕捉到扭轉這個局面(只要你的名單沒有填寫...)

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

上面應該提到這一點,但是需要將標題和數據拆分爲arunkumar的原因是:你不能指望'dict.items()'以可預測的順序給你鍵。恰恰相反,從數據中拆分標題也可以簡化模板結構。 –

+0

我已經更新了代碼來照顧填充列表。應該刪除需要初始化空矩陣(前面)。 –

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>"  
+0

這不起作用。首先,我需要組織數據,以便將它傳遞給Django模板(當然,我可以將它存儲在字符串中而不是打印出來,但我更願意在模板中完成所有的演示文稿)。第二點是,這將打印與其自己的行中每個標題相關的所有數據。我想在一個專欄中提供這些信息。 –

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

我真的需要一個做更多的定製到HTML,這是我沒有使用這個解決方案的唯一原因。這和[歐文的解決方案如下](http:// stackoverflow。com/questions/6884250/how-to-render-a-python-dict-as-an-html-table-with-vertical-columns/6885140#6885140)工作得很好。 –