I am trying to allow the user to download a CSV file with data defined by their actions. The file doesn’t exist, it’s created dynamically. How can I do this in Flask?
Answers:
Thank you for visiting the Q&A section on Magenaut. Please note that all the answers may not help you solve the issue immediately. So please treat them as advisements. If you found the post helpful (or not), leave a comment & I’ll get back to you as soon as possible.
Method 1
Generate the data with csv.writer and stream the response. Use StringIO to write to an in-memory buffer rather than generating an intermediate file.
import csv
from datetime import datetime
from io import StringIO
from flask import Flask
from werkzeug.wrappers import Response
app = Flask(__name__)
# example data, this could come from wherever you are storing logs
log = [
('login', datetime(2015, 1, 10, 5, 30)),
('deposit', datetime(2015, 1, 10, 5, 35)),
('order', datetime(2015, 1, 10, 5, 50)),
('withdraw', datetime(2015, 1, 10, 6, 10)),
('logout', datetime(2015, 1, 10, 6, 15))
]
@app.route('/')
def download_log():
def generate():
data = StringIO()
w = csv.writer(data)
# write header
w.writerow(('action', 'timestamp'))
yield data.getvalue()
data.seek(0)
data.truncate(0)
# write each log item
for item in log:
w.writerow((
item[0],
item[1].isoformat() # format datetime as string
))
yield data.getvalue()
data.seek(0)
data.truncate(0)
# stream the response as the data is generated
response = Response(generate(), mimetype='text/csv')
# add a filename
response.headers.set("Content-Disposition", "attachment", filename="log.csv")
return response
If the generate function will need information from the current request, it should be decorated with stream_with_context, otherwise you will get a “working outside request context” error. Everything else remains the same.
from flask import stream_with context
@stream_with_context
def generate():
...
Method 2
The Flask-Excel library uses PyExcel to generate a CSV or other spreadsheet format and produces a Flask response. The docs list how to produce other formats and the full API for what data can be used.
pip install flask-excel
import flask_excel as excel
@app.route('/download', methods=['GET'])
def download_data():
sample_data=[0, 1, 2]
excel.init_excel(app)
extension_type = "csv"
filename = "test123" + "." extension_type
d = {'colName': sample_data}
return excel.make_response_from_dict(d, file_type=extension_type, file_name=filename)
All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0