循环jinja2模板中的csv内容

时间:2017-08-04 20:11:07

标签: python jinja2

我正在尝试使用csv作为输入基于jinj2模板构建输出。我搜索并找不到很多信息来构建解决方案。

到目前为止,我有以下代码:

import sys, os
import jinja2
import csv

in_file="csv_file.csv"
jinja_template = "test.j2"
env = jinja2.Environment(loader=jinja2.FileSystemLoader(searchpath="."))

with open(in_file, "rb") as FD:
    reader = csv.DictReader(FD)
    for vals in reader:
        gen_template = env.get_template(jinja_template)
        output = gen_template.render(vals)
        print output

我的csv文件如下所示:

country,city
UK,London
UK,Manchester
UK,Liverpool
US,Chicago
US,Denver
US,Atlanta

我的jinja2模板看起来像这样:

country: {{country}} has cities {{city}}

以下是我想要实现的输出:

country: UK has cities: London, Manchester, Liverpool
country: US has cities: Chicago, Denver, Atlanta

我认为我需要在j2模板中运行for循环,以便在该国家/地区旁边建立城市名称。

当我运行上面的代码时,我实际上得到了各个国家<>城市名称分别如此:

country: UK has cities London
country: UK has cities Manchester
country: UK has cities Liverpool
country: US has cities Chicago
country: US has cities Denver
country: US has cities Atlanta

感谢有人能提供一些关于如何实现这一目标的指示。

1 个答案:

答案 0 :(得分:0)

假设您的输入csv按国家/地区排序,itertools.groupby可以提供帮助:

from io import StringIO
from jinja2 import Template
from itertools import groupby
from operator import itemgetter
from csv import DictReader


csv_data = '''country,city
UK,London
UK,Manchester
UK,Liverpool
US,Chicago
US,Denver
US,Atlanta
'''

tmpl = 'country: {{country}} has cities {{cities}}'
template = Template(tmpl)

with StringIO(csv_data) as file:
    rows = DictReader(file)
    for country, groups in groupby(rows, key=itemgetter('country')):
        cities = ', '.join(row['city'] for row in groups)
        output = template.render(country=country, cities=cities)
        print(output)

打印

country: UK has cities London, Manchester, Liverpool
country: US has cities Chicago, Denver, Atlanta

如果您更喜欢在jinja中使用join,这是一个选项:

tmpl = 'country: {{country}} has cities {{cities | join(", ")}}'
template = Template(tmpl)

with StringIO(csv_data) as file:
    rows = DictReader(file)
    for country, groups in groupby(rows, key=itemgetter('country')):
        cities = (row['city'] for row in groups)
        output = template.render(country=country, cities=cities)

如果您需要能够附加标题,则需要先从文件中收集所有数据(使用OrderedDict完成此处):

from collections import OrderedDict

tmpl = '''Countries and cities:
{%-for country, cities in grouped.items()%}
country: {{coutry}} has cities {{cities | join(", ")}}
{%-endfor%}'''
template = Template(tmpl)

with StringIO(csv_data) as file:
    rows = DictReader(file)
    grouped = OrderedDict()
    for country, groups in groupby(rows, key=itemgetter('country')):
        grouped[country] = [item['city'] for item in groups]
    output = template.render(grouped=grouped)
    print(output)

然后产生:

Countries and cities:
country:  has cities London, Manchester, Liverpool
country:  has cities Chicago, Denver, Atlanta