I have an app that takes in some information, performs some calculations using pandas, and turns the final pandas data frame into a CSV that is then downloaded using the Flask app. How do I download multiple CSVs within one view? It seems that I can only return a single response at a time.
An example snippet:
def serve_csv(dataframe,filename):
buffer = StringIO.StringIO()
dataframe.to_csv(buffer, encoding='utf-8', index=False)
buffer.seek(0)
return send_file(buffer,
attachment_filename=filename,
mimetype='text/csv')
def make_calculation(arg1, arg2):
'''Does some calculations.
input: arg1 - string, arg2- string
returns: a pandas data frame'''
@app.route('test_app', methods=['GET', 'POST'])
def test_app():
form = Form1()
if form.validate_on_submit():
calculated_dataframe = make_calculation(str(form.input_1.data), str(form.input_2.data))
return serve_csv(calculated_dataframe, 'Your_final_output.csv')
return render_template('test_app.html', form=form)
So let's say in that example above that make_calculation
returned two pandas data frames. How would I print both of them to a CSV?
This is all the code you need using the Zip files
. It will return a zip file with all of your files.
In my program everything I want to zip is in an output
folder so i just use os.walk
and put it in the zip file with write
. Before returning the file
you need to close it, if you don't close it will return an empty file.
import zipfile
import os
from flask import send_file
@app.route('/download_all')
def download_all():
zipf = zipfile.ZipFile('Name.zip','w', zipfile.ZIP_DEFLATED)
for root,dirs, files in os.walk('output/'):
for file in files:
zipf.write('output/'+file)
zipf.close()
return send_file('Name.zip',
mimetype = 'zip',
attachment_filename= 'Name.zip',
as_attachment = True)
In the html
I simply call the route:
<a href="{{url_for( 'download_all')}}"> DOWNLOAD ALL </a>
I hope this helped somebody. :)
You could return a MIME Multipart response, a zip file, or a TAR ball (please note the linked RFC is somewhat out of date, but is easier to quickly get up to speed with because it's in HTML; the official one is here).
If you choose to do a MIME multipart response, a good starting point might be to look at the MultipartEncoder
and MultipartDecoder
in requests toolbelt; you may be able to use them directly, or at least subclass/compose using those to get your desired behavior. Zip files and TAR balls can be implemented using standard library modules.
An alternative would be to design your API so that you were returning JSON, use a header (or XML element or JSON field) to indicate that additional CSVs could be obtained by another request, or similar.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With