#はじめに
PythonのフレームワークであるFlask上で、csvでファイルをダウンロードする必要がありました。今回はSQLAlchemyを使ってDB上のデータをcsvに変換して、FlaskのAPIを使ってダウンロードできるようしました。
#Flaskでcsvダウンロード
ダウンロードするデータは以下のような形式になってるとします。シンプルなFlaskアプリケーションで、今回はusersテーブルを作成しておきましょう。このテーブルのデータをDBから取得して、csv形式でダウンロードできるようにします。
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime
from io import StringIO
app = Flask(__name__)
DB_URL = <DBのURI>
app.config['SQLALCHEMY_DATABASE_URI'] = DB_URI
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)
#サンプルデータのスキーマ
class User(db.Model):
__tablename__ = "users"
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(200))
gender = db.Column(db.Integer)
age = db.Column(db.Integer)
created_at = db.Column(db.DateTime)
def __init__(self, username, gender, age):
self.username = username
self.gender = gender
self.age = age
now = datetime.now()
self.created_at = now
def __repr__(self):
return '<User %r>' % self.username
今回はダウンロードを/download/~から実行できるようにします。
@app.route('/download/<obj>/')
def download(obj):
f = StringIO()
writer = csv.writer(f, quotechar='"', quoting=csv.QUOTE_ALL, lineterminator="\n")
if obj == 'users':
writer.writerow(['id','username','gender','age','created_at'])
for u in User.query.all():
writer.writerow([u.id, u.username,u.gender,u.age,u.created_at])
res = make_response()
res.data = f.getvalue()
res.headers['Content-Type'] = 'text/csv'
res.headers['Content-Disposition'] = 'attachment; filename='+ obj +'.csv'
return res
肝はContent-Disposition
ヘッダーであり、このヘッダーの値に応じてブラウザ上でインラインで表示されるか、アタッチメントとして処理されるか決まります。
今回はattachment
と指定して、添付ファイル化します。ダウンロードされる際のファイル名はfilename=
で指定することができます。
Flaskでレスポンスの形式を弄るときはmake_response()
を弄ればOKです
またpythonでcsvに変換するときはStringIO
を使用しましょう。
#終わりに
方法は単純で、データをcsv形式に変換して、レスポンスの際にHTTPヘッダーを書き換えるだけです。ダウンロードという簡単な機能ですが、HTTPについてあまり知らないと少し引っかかってしまうかもしれません。