我正在尝试使用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
感谢有人能提供一些关于如何实现这一目标的指示。
答案 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