1

I have a basic flask app where data frames are formed from two CSVs and some transformations happen and on the HTML page , a final result dataframe can be seen in a tabular format. It works fine till here.

Apart from that, I also want the user to have an option to download the same table as a CSV.

Below is my flask code:

from flask import *
import pandas as pd
app = Flask(__name__)
@app.route("/tables")
def show_tables():
     df1 = pd.read_csv('daily.csv')
     df2 = pd.read_csv('companies.csv')
     df1['date']= pd.to_datetime(df1['date'], format='%m/%d/%y')
     df3 = pd.merge(df1,df2,how='left',on='id')
     dates = pd.DataFrame({"date": pd.date_range("2017-01-01", "2017-01-10")})
     df4 = (df3.groupby(['id', 'name'])['date', 'value']
 .apply(lambda g: g.merge(dates, how="outer"))
 .fillna(0)
 .reset_index(level=[0,1])
 .reset_index(drop=True))
     df4 = df4.sort_values(by=['id','date'])
     df4.value = df4.value.astype(int)
     df4['difference'] = df4.groupby('id')['value'].diff()
     return render_template('view.html',tables=[df4.to_html(classes='Company_data')],
     titles = [ 'Company_data'],filename=df4.to_csv())
@app.route('/tables_download/<filename>')
def tables_download(filename):
    return response(filename)  //--right way to pass the csv file?


if __name__ == "__main__":
    app.run()

Below is my HTML code:

      <!doctype html>
<title>Simple tables</title>
<link rel=stylesheet type=text/css href="{{ url_for('static', filename='style.css') }}">
<div class=page>
  <h1>Company data</h1>
  {% for table in tables %}
    <h2>{{titles[loop.index]}}</h2>
    {{ table|safe }}
  {% endfor %}
</div>

<a href="{{ url_for('tables_download', filename=filename) }}">Download</a>

On my HTML page, I don't even see the Download option.

Struggling to figure out what's wrong so looking for help

optimus_prime
  • 817
  • 2
  • 12
  • 34

1 Answers1

0

As documented in the Flask API, I believe that send_file or send_from_directory would be the way to implement this.

@app.route('/uploads/<path:filename>')
def download_file(filename):
    return send_from_directory(app.config['UPLOAD_FOLDER'], filename, as_attachment=True)

These are both documented on http://flask.pocoo.org/docs/0.12/api/

send_from_directory is more secure (if used correctly) as it limits the file available to download to just those in a specific directory preventing any 'hackers' from downloading your private information.

scotty3785
  • 6,763
  • 1
  • 25
  • 35
  • Cool. So, in my case I am generating the file right away by converting a dataframe to csv. So, what should be the upload folder? – optimus_prime Apr 24 '17 at 16:26
  • Ah. I had missed that part. Perhaps the answer to [this question](http://stackoverflow.com/questions/30024948/flask-download-a-csv-file-on-clicking-a-button) will help you. – scotty3785 Apr 24 '17 at 16:38
  • Or perhaps [this example](http://code.runnable.com/UiIdhKohv5JQAAB6/how-to-download-a-file-generated-on-the-fly-in-flask-for-python) – scotty3785 Apr 24 '17 at 16:39
  • Second example seems like my case, but the solution seems incomplete – optimus_prime Apr 24 '17 at 16:44