Как сделать Python dict как HTML-таблицу с вертикальными столбцами - PullRequest
6 голосов
/ 30 июля 2011

У меня есть python, где каждый ключ соответствует заголовку, а список, связанный с каждым заголовком, содержит произвольное количество значений:

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

Ответы [ 3 ]

5 голосов
/ 30 июля 2011

Если мы немного изменим игру, это совсем несложно изменить (если ваши списки не заполнены ...)

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>
2 голосов
/ 31 июля 2011

Кеннет Рейтц предположил, что вы также можете решить эту проблему, используя 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>
0 голосов
/ 30 июля 2011

Попробуйте код ниже. Обратите внимание, что поскольку вы используете ассоциативный массив для данных, порядок появления заголовков не может быть гарантирован.

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>"    
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...