2017-08-08 69 views
0

我正在使用Django的StreamingHttpResponse来流式传输大型CSV文件。据the docs,迭代器传递到响应的streaming_content参数:手动添加行到StreamingHttpResponse(Django)

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的生成/流数据写入输出数据集。

回答

1

答案是与发电机的功能,而不是计算他们的飞行(StreamingHttpResponse的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 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