Posted at

Djangoで取得件数の多いSQLの結果をcsvとしてエクスポートさせる

More than 1 year has passed since last update.

SQLの実行結果をCSVとしてエクスポートさせることは多々あるんですが、

その件数結果が多すぎてタイムアウトが発生したとか、メモリを使いすぎてwebサーバが爆発:boom:した……ということも稀にあったりします。

ので、少しずつ取得しつつ結果をcsvとして出力する方法を備忘録も兼ねて。


準備するもの!

class Echo(object):

def write(self, value):
return value

def yield_query(query):
filter_id = 0

while True:
rows = list(query.filter(id__gt=filter_id).order_by('id')[:1000])

if len(rows) == 0:
break

for row in rows:
yield row

filter_id = rows[-1].id

def stream_csv_response(rows):
writer = csv.writer(Echo())

response = StreamingHttpResponse(
(writer.writerow(row) for row in rows),
content_type="text/csv"
)

response['Content-Disposition'] = 'attachment; filename="big.csv"'

return response


  • yield_queryは、渡されたqueryを少しずつ実行していく関数です。

  • stream_csv_responseは、yield_queryの実行結果を引数rowsで受け取り、Djangoのresponseを返してあげる関数です。


呼び方!

# 適当なModelを用意

test_query = Test.objects

# yieldを返すobjectを取得
yield_rows = yield_query(test_query)

# レスポンスの返却
return stream_csv_response(yield_rows)

ね、簡単でしょ?