我正在使用Django的StreamingHttpResponse来动态传输大型CSV文件。根据{{3}},迭代器被传递给响应的streaming_content
参数:
import csv
from django.http import StreamingHttpResponse
def get_headers():
return ['field1', 'field2', 'field3']
def get_data(item):
return {
'field1': item.field1,
'field2': item.field2,
'field3': item.field3,
}
# StreamingHttpResponse requires a File-like class that has a 'write' method
class Echo(object):
def write(self, value):
return value
def get_response(queryset):
writer = csv.DictWriter(Echo(), fieldnames=get_headers())
writer.writeheader() # this line does not work
response = StreamingHttpResponse(
# the iterator
streaming_content=(writer.writerow(get_data(item)) for item in queryset),
content_type='text/csv',
)
response['Content-Disposition'] = 'attachment;filename=items.csv'
return response
我的问题是:如何在CSV编写器上手动编写行?手动调用writer.writerow(data)或writer.writeheader()(也在内部调用writerow())似乎不会写入数据集,而只是将来自streaming_content的生成/流数据写入输出数据集。 / p>
答案 0 :(得分:4)
答案是使用生成器函数产生结果,而不是动态计算它们(在StreamingHttpResponse的streaming_content
参数内)并使用我们创建的伪缓冲区(Echo Class)来向响应写入一行:
import csv
from django.http import StreamingHttpResponse
def get_headers():
return ['field1', 'field2', 'field3']
def get_data(item):
return {
'field1': item.field1,
'field2': item.field2,
'field3': item.field3,
}
# StreamingHttpResponse requires a File-like class that has a 'write' method
class Echo(object):
def write(self, value):
return value
def iter_items(items, pseudo_buffer):
writer = csv.DictWriter(pseudo_buffer, fieldnames=get_headers())
yield pseudo_buffer.write(get_headers())
for item in items:
yield writer.writerow(get_data(item))
def get_response(queryset):
response = StreamingHttpResponse(
streaming_content=(iter_items(queryset, Echo())),
content_type='text/csv',
)
response['Content-Disposition'] = 'attachment;filename=items.csv'
return response
答案 1 :(得分:0)
建议的解决方案实际上可能导致CSV错误/不匹配(报头与数据不匹配)。您想要用以下内容替换受影响的部分:
header = dict(zip(fieldnames, fieldnames))
yield writer.writerow(header)
相反。这来自writeheader
https://github.com/python/cpython/blob/08045391a7aa87d4fbd3e8ef4c852c2fa4e81a8a/Lib/csv.py#L141:L143
由于某些原因,yield
的运行状况不佳
希望这对以后的人有所帮助:)
还请注意,由于此PR,如果使用python 3.8+,则无需修复:https://bugs.python.org/issue27497