첨부 파일 다운로드로 csv 파일을 스트리밍하려고합니다. CSV 파일의 크기가 4MB 이상으로 늘어나고 있으며 모든 데이터가 만들어지고 메모리에 먼저 전달되기를 기다리지 않고 사용자가 파일을 적극적으로 다운로드 할 수있는 방법이 필요합니다.Django에서 CSV 파일 스트리밍
처음에는 장고의 FileWrapper
클래스를 기반으로하는 파일 래퍼를 사용했습니다. 그건 실패했다. 그 때 나는 응답 스트림 발전기를 사용하여 여기하는 방법을 보았다 : 나는 발전기 내에서 오류가 발생하면 How to stream an HttpResponse with Django
, 나는 내가 get_row_data()
기능을 적절한 데이터를 생성하고 볼 수 있지만를 내가하려고 할 때 비어있는 응답을 반환하십시오. 또한 장고를 비활성화했습니다 GZipMiddleware
. 아무도 내가 뭘 잘못하고 있는지 알아?
편집 : 문제는 ConditionalGetMiddleware
입니다. 나는 그것을 대체해야했다, 코드는 아래 답변에있다. 여기
from django.views.decorators.http import condition @condition(etag_func=None) def csv_view(request, app_label, model_name): """ Based on the filters in the query, return a csv file for the given model """ #Get the model model = models.get_model(app_label, model_name) #if there are filters in the query if request.method == 'GET': #if the query is not empty if request.META['QUERY_STRING'] != None: keyword_arg_dict = {} for key, value in request.GET.items(): #get the query filters keyword_arg_dict[str(key)] = str(value) #generate a list of row objects, based on the filters objects_list = model.objects.filter(**keyword_arg_dict) else: #get all the model's objects objects_list = model.objects.all() else: #get all the model's objects objects_list = model.objects.all() #create the reponse object with a csv mimetype response = HttpResponse( stream_response_generator(model, objects_list), mimetype='text/plain', ) response['Content-Disposition'] = "attachment; filename=foo.csv" return response
내가 응답 스트림에 사용하는 발전기입니다 : def get_row_data(model, row):
"""Get a row of csv data from an object"""
#Create a temporary csv handle
csv_handle = cStringIO.StringIO()
#create the csv output object
csv_output = csv.writer(csv_handle)
value_list = []
for field in model._meta.fields:
#if the field is a related field (ForeignKey, ManyToMany, OneToOne)
if isinstance(field, RelatedField):
#get the related model from the field object
related_model = field.rel.to
for key in row.__dict__.keys():
#find the field in the row that matches the related field
if key.startswith(field.name):
#Get the unicode version of the row in the related model, based on the id
try:
entry = related_model.objects.get(
id__exact=int(row.__dict__[key]),
)
except:
pass
else:
value = entry.__unicode__().encode("utf-8")
break
#if it isn't a related field
else:
#get the value of the field
if isinstance(row.__dict__[field.name], basestring):
value = row.__dict__[field.name].encode("utf-8")
else:
value = row.__dict__[field.name]
value_list.append(value)
#add the row of csv values to the csv file
csv_output.writerow(value_list)
#Return the string value of the csv output
return csv_handle.getvalue()
: 여기 def stream_response_generator(model, objects_list):
"""Streaming function to return data iteratively """
for row_item in objects_list:
yield get_row_data(model, row_item)
time.sleep(1)
을 그리고 난 CSV 행 데이터를 생성하는 방법을 여기
은이다
아직 데이터를 스트리밍 할 필요가 없지만 간단하고 우아한 것을 얻는 것이 얼마나 빠르는지 아는 것이 좋습니다. –
나는이 답변을 정말 좋아하지만 이것이 내 문제가 아니라는 사실이 밝혀졌습니다. 당신이 쓴이 정확한 코드를 문자 그대로 사용했습니다. 단지 응답을 생성 할 것인지를보기 위해서였습니다. 그러나 응답은 0 바이트로 돌아옵니다. 그래서 저는 여전히 같은 결과에 갇혀 있습니다. – bfrederix
이 코드는 제대로 작동하므로 문제 해결에 필요한 환경에 문제가 있습니다. –