简体   繁体   English

在jinja2模板中循环csv内容

[英]loop csv content in a jinja2 template

i am trying to build an output based on a jinj2 template using a csv as input. 我正在尝试使用csv作为输入基于jinj2模板构建输出。 I've search through and couldnt find much information to build a solution. 我已经搜索过,无法找到很多信息来建立解决方案。

So far i have the following code: 到目前为止,我有以下代码:

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

My csv file looks like this: 我的csv文件如下所示:

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

And my jinja2 template looks like this: 我的jinja2模板如下所示:

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

Following is the output i am trying to achieve: 以下是我尝试实现的输出:

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

I believe i need to run for loop within the j2 template in order to build the city names next to the country. 我相信我需要在j2模板中运行for loop以便在国家旁边建立城市名称。

When i run the code above i actually get the individual country <> city names as seperately like this: 当我运行上面的代码时,我实际上得到的是单独的国家<>城市名称,如下所示:

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

Appreciate if someone can provide some pointers on how i can achieve this. 赞赏是否有人可以提供一些有关我如何实现这一目标的指示。

assuming your input csv is sorted by country, itertools.groupby can help: 假设您输入的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)

which prints 哪个打印

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

if you prefer to do the join inside jinja, this is an option: 如果你喜欢做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)

if you need to be able to append a header, you need to collect all the data from your file first (done here using an OrderedDict): 如果您需要能够附加标题,则需要首先从文件中收集所有数据(使用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)

which then yields: 然后产生:

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

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

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