繁体   English   中英

在python中创建数据结构以在Jinja2模板中使用

[英]Creating a data structure in python for use in a Jinja2 template

我想使用python读取CSV数据,然后使用Jinja2将其输出以制作平面文件HTML报告。 我要使用的CSV数据如下:

State,City,Issue,Date
Michigan,Detroit,Economic Issues,12/11/14
Michigan,Detroit,Poor Schools,12/11/14
Michigan,Battle Creek,Economic Issues,2/12/14
Georgia,Atlanta,Lack of Transit,2/12/14
Georgia,Atlanta,Traffic,2/12/14
Georgia,Cummings,Economic Issues,12/11/14
Georgia,Cummings,Poor Schools,12/11/14
Georgia,Athens,Traffic,12/11/14
Florida,Miami,Weather Issues,12/11/14
Florida,Miami,Poor Schools,2/12/14
Florida,Miami,Economic Issues,2/12/14
Florida,Miami,Lack of Transit,2/12/14
Florida,Sarasota,Economic Issues,2/12/14
Florida,Levy,Poor Schools,2/12/14
Florida,Lee,Traffic,2/12/14
California,Los Angeles,Traffic,12/11/14
Alaska,Anchorage,Weather Issues,2/12/14

我想为每个州分配一行,然后在其下包含每个城市以及相关的发行和日期。

输出将类似于以下内容:

Michigan
        Detroit        Economic Issues        12/11/2014
                       Poor Schools           12/11/2014
        Battle Creek   Economic Issues        02/12/2014
Georgia
        Atlanta        Lack of Transit        02/12/2014
                       Traffic                02/12/2014
        Cummings       Economic Issues        12/11/2014

我喜欢使用Jinja2并为此数据的输出创建模板。 我的问题是我不确定构造此数据然后移交给模板的最佳方法。

我应该创建一个国家词典,列出每个城市,发行和日期信息吗? 应该只是列表列表吗? 我对数据结构的外观感到非常困惑,因此我可以轻松地在Jinja2模板中进行迭代。

您可以使用groupby()过滤器在模板中对序列进行分组:

<table>
{% for state in csvrows|groupby('State') %}
    <tr><td rowspan="4">{{ state.grouper }}</td></tr>
    {% for city in state.list|groupby('City') %}
        {% for row in city.list %}
            <tr>
                <td>{% if loop.first %}{{ row.City }}{% endif %}</td>
                <td>{{ row.Issue }}</td>
                <td>{{ row.Date }}</td>
            </tr>
        {% endfor %}
    {% endfor %}
{% endfor %}
</table>

所述groupby()滤波器产生组对象,每个listgrouper属性。 后者是在其上构建组的值(因此,外循环中的State值,下一个循环中的City.list属性是均具有相同StateCity值的值序列。

然后,您需要制作的是一系列字典; groupby()过滤器甚至可以对您的数据进行排序。 只需将一个csv.DictReader()对象传递给Jinja2,便一切就绪。

Jinja中的groupby()过滤器的工作原理几乎与itertools.groupby()函数完全一样,使用该函数 ,您可以通过一些打印语句产生相同的所需输出:

>>> from itertools import groupby
>>> from operator import itemgetter
>>> state_key = itemgetter('State')
>>> for state, cities in groupby(sorted(rows, key=state_key), state_key):
...     print state
...     city_key = itemgetter('City')
...     for city, group in groupby(sorted(cities, key=city_key), city_key):
...         print '\t', city
...         for row in group:
...             print '\t\t', row['Issue'], row['Date']
... 
Alaska
    Anchorage
        Weather Issues 2/12/14
California
    Los Angeles
        Traffic 12/11/14
Florida
    Lee
        Traffic 2/12/14
    Levy
        Poor Schools 2/12/14
    Miami
        Weather Issues 12/11/14
        Poor Schools 2/12/14
        Economic Issues 2/12/14
        Lack of Transit 2/12/14
    Sarasota
        Economic Issues 2/12/14
Georgia
    Athens
        Traffic 12/11/14
    Atlanta
        Lack of Transit 2/12/14
        Traffic 2/12/14
    Cummings
        Economic Issues 12/11/14
        Poor Schools 12/11/14
Michigan
    Battle Creek
        Economic Issues 2/12/14
    Detroit
        Economic Issues 12/11/14
        Poor Schools 12/11/14

这是直接从您的示例CSV数据生成的; 过滤器也会应用排序,就像上面的python示例一样。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM