LoginSignup
14
22

More than 5 years have passed since last update.

Flaskでcsvダウンロード機能を作成する

Posted at

はじめに

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についてあまり知らないと少し引っかかってしまうかもしれません。

参照

MDN web docs: Content-Disposition

14
22
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
22