在Django模板中使用标签打印矩阵的正确方法是什么?

时间:2015-02-11 15:14:09

标签: django django-templates django-views nested-loops

我想在Django中做一些非常简单的事情:将矩阵打印为HTML表格,并为行和列添加标签。这些是我认为的变量:

matrix = np.array([
    [101, 102, 103],
    [201, 202, 203],
])
colnames = ['Foo', 'Bar', 'Barf']
rownames = ['Spam', 'Eggs']

我想要一个看起来像这样的表:

      Foo  Bar  Barf
Spam  101  102  103
Eggs  201  202  203

我的模板代码如下所示:

<table>
    <tr>
        <th></th>
        {% for colname in colnames %}
            <th>{{ colname }}</th>
        {% endfor %}
    </tr>
    {% for rowname in rownames %}{% with forloop.counter0 as rowindex %}
        <tr>
            <th>{{ rowname }}</th>
            {% for colname in colnames %}{% with forloop.counter0 as colindex %}
                <td>TABLECELL</td>
            {% endwith %}{% endfor %}
        </tr>
    {% endwith %}{% endfor %}
</table>

TABLECELL的不同值的输出:

{{ rowindex }}, {{ colindex }} - &gt;带索引的表:)

{{ matrix.0.0 }} - &gt;满桌的101s:)

{{ matrix.rowindex.colindex }} - &gt;带有空单元格的表:(

由于前两项工作正常,因此假设最后一项会给出预期结果似乎并不疯狂。我唯一的解释是rowindexcolindex可能是字符串 - 当然int()是Django模板中禁止的许多内容。

有谁知道我怎么做这个工作?或者理想情况: 有谁知道这是如何在Django中完成的?

编辑1:

似乎我必须将枚举列表传递给模板。我将它们提供为enum_colnamesenum_rownames,但现在我甚至无法执行嵌套for循环:

<table>
    <tr>
        <th></th>
        {% for unused_colindex, colname in enum_colnames %}
            <th>{{ colname }}</th>
        {% endfor %}
    </tr>
    {% for rowindex, rowname in enum_rownames %}
        <tr>
            <th>{{ rowname }}</th>
            {% for doesnt_work_anyway in enum_colnames %}
                <td>You don't see me.</td>
            {% endfor %}
        </tr>
    {% endfor %}
</table>

这会给出一个表格,其中所有<th> s都填充了正确的标签,但根本没有<td>

编辑2:

我找到了一个疯狂的“解决方案”,我在这里作为一个“有效”的例子发布,但显然不是我的问题的答案 - 这个应该如何在Django中完成。它来了:

derp = ['', 'Foo', 'Bar', 'Barf', 'Spam', 101, 102, 103, 'Eggs', 201, 202, 203]
iderp = enumerate(derp)
<table>
    {% for i, d in iderp %}
        {% if i < 4 %}  <!-- if top row: th -->
            {% cycle '<tr><th>' '<th>' '<th>' '<th>' %}
        {% else %}  <!-- else: td -->
            {% cycle '<tr><th>' '<td>' '<td>' '<td>' %}
        {% endif %}
            {{ d }}
        {% if i < 4 %}  <!-- if top row: th -->
            {% cycle '</th>' '</th>' '</th>' '</th></tr>' %}
        {% else %}  <!-- else: td -->
            {% cycle '</th>' '</th>' '</td>' '</td></tr>' %}
        {% endif %}
    {% endfor %}
</table>

请注意它只能用于此特定宽度的表格。所以在这种形式下,它甚至不是最初问题的真正解决方案。

2 个答案:

答案 0 :(得分:4)

感谢Paulo Almeida在他的回答中提供了两个基本提示:

  • 表格 - 包括标签 - 应该在视图中构建。

  • forloop.first可用于将标签放入<th> s。

table = [
    ['', 'Foo', 'Bar', 'Barf'],
    ['Spam', 101, 102, 103],
    ['Eggs', 201, 202, 203],
]
<table>
    {% for row in table %}
        <tr>
        {% for cell in row %}
            {% if forloop.first or forloop.parentloop.first %} <th> {% else %} <td> {% endif %}
                {{ cell }}
            {% if forloop.first or forloop.parentloop.first %} </th> {% else %} </td> {% endif %}
        {% endfor %}
        </tr>
    {% endfor %}
</table>

我想我的隐含问题的答案 - 如何从模板中访问多维数组的值 - 这是不可能的。

答案 1 :(得分:1)

您的问题似乎是a feature request suggesting the use of iterables in the cycle tag的一个很好的用例。然后,您可以在第一个{% cycle rownames %}<td>

不幸的是,据我所知,这是不可能的。我会将这个逻辑从模板转移到视图中(或者更可能是实用函数或模型方法,具体取决于具体情况),构建一个易于在模板中处理的列表:

table = [
    ['Spam', 101, 102, 103],
    ['Eggs', 201, 202, 203],
]

构建表的功能可能如下所示:

def build_table(rownames, matrix):
    table = []
    for rowname, values in zip(rownames, matrix):
        row = [rowname]
        row.extend(values.tolist())
        table.append(row)
    return table