Flask で CSV 出力(修正版)

前回はファイルを書き込んで閉じてから、また開いてと、かなり気持ち悪かったのですが、



と、修正案を頂いたので、適用してみました。
これで余分な一時ファイルも作られないのですっきり。
StringIO を使うのか!と、また1つ勉強になりました。


V 様に感謝。


# -*- coding: utf-8 -*-
import codecs
import csv
import cStringIO
from flask import Flask, Response, make_response, render_template
app = Flask(__name__)


@app.route("/")
def root():
    return Response("<a href='/dl/'>DL</a>")


@app.route("/dl/")
def make_csv():
    """
    CSV 出力
    """
    response = make_response()
    response.data = _get_csv_data()
    response.headers['Content-Type'] = 'application/octet-stream'
    response.headers['Content-Disposition'] = u'attachment; filename=データ.csv'
    return response


def _get_csv_data():
    """
    CSV データ作成
    """
    data = _make_data()
    csv_file = _make_file(data)
    return csv_file


def _make_data():
    """
    書き込みデータ作成
    """
    result = []
    result.append(("1", "p", "python", 100, "あ"))
    result.append(("2", "y", "python", 200, "い"))
    result.append(("3", "t", "python", 300, "う"))
    result.append(("4", "h", "python", 400, "え"))
    result.append(("5", "o", "python", 500, "お"))
    result.append(("6", "n", "python", 600, "か"))
    return result


def _make_file(data):
    """
    データを CSV 形式に変換
    """
    csv_file = cStringIO.StringIO()
    writer = csv.writer(csv_file, quoting=csv.QUOTE_NONNUMERIC)
    writer.writerows(data)
    return csv_file.getvalue()


if __name__ == '__main__':
    app.run(debug=True)


コメントも追加してみたり。
これで多少は実用に耐えられるかなー。


追記:出力を Shift-JIS にする場合、

 -    response.data = _get_csv_data()
 +   response.data = _get_csv_data().decode('utf8').encode('sjis')

と「.decode('utf8').encode('sjis')」つけるだけでできます。
これは CSV に限らず、HTML 出力の場合でも出来るので色々使えそう。