2017-08-08 71 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