Search code examples
pythonpandasdataframeflaskpython-routes

pandas/flask: buttons to download dataframes


I am working on replicating a tkinter interface in flask. I have pandas dataframes that are displayed on the page using "to_html()". I used [this tutorial][1]. But I need to create buttons to download the dataframes.

The functions that create, and download, the dataframes are in a custom module in its own directory "/testmodule". The functions for downloading the dataframes are separate from the function that creates and displays the dataframes.

Here is the example code for testmodule.py:

import pandas as pd
from Flask import render_template
def df_test():
    df1 = pd.DataFrame(
        {
        'terms' : ['term1','term2'],
        'code1': ['1234x', '4321y'],
        'code2': ['2345x','5432y'],
        'code3': ['3456x','6543y']
        }
        )
    df2 = pd.DataFrame(
         {
        'name': ['Dan','Sara','Conroy'],
        'rate': ['3','3.5','5.2'],
        'location': ['FL','OH','NM'],
        'code': ['4444g','6543y','2345x']                           
         })
    return render_template('view.html',tables=[df1.to_html(classes='female'), df2.to_html(classes='male')],
    titles = ['na', 'Codes', 'People'])

def download_df():
    output_file = 'codes_people.xlsx'
    writer = pd.ExcelWriter(output_file, engine='xlsxwriter')
    df1.to_excel(writer, sheet_name="Codes")
    df2.to_excel(writer, sheet_name="People")
    workbook  = writer.book
    worksheet1 = writer.sheets['Codes']
    worksheet2 = writer.sheets['People']
    writer.save()

I have tried writing a route for the download, but get errors that dataframe values aren't defined, which I understand, because I'm importing a function call for download_df separately from the function that created the dfs. I just don't know how to pass the values of df1 and df2 from the first function into the second function once it is in routes.py

I am going to have buttons that will allow for downloads of new dfs made from columns of the existing 2.

Can the buttons call the download function (download_df) from the template itself, or can this only be done by setting a function in routes.py? If routes.py, how do I pass the df variables to routes? Or, do I need to create a temp file?

[1]: https://sarahleejane.github.io/learning/python/2015/08/09/simple-tables-in-webapps-using-flask-and-pandas-with-python.html/ \


Solution

  • What ended up working was including the file-creation commands in the first view along with the dataframes, then setting a session variable to pass the file name of the output file to the download view.

    def df_test():
        df1 = pd.DataFrame(
            {
            'terms' : ['term1','term2'],
            'code1': ['1234x', '4321y'],
            'code2': ['2345x','5432y'],
            'code3': ['3456x','6543y']
            }
            )
        df2 = pd.DataFrame(
             {
            'name': ['Dan','Sara','Conroy'],
            'rate': ['3','3.5','5.2'],
            'location': ['FL','OH','NM'],
            'code': ['4444g','6543y','2345x']                           
             })
        writer = pd.ExcelWriter(output_file, engine='xlsxwriter')
        df1.to_excel(writer, sheet_name="Codes")
        df2.to_excel(writer, sheet_name="People")
        workbook  = writer.book
        worksheet1 = writer.sheets['Codes']
        worksheet2 = writer.sheets['People']
        writer.save()
        return render_template('view.html',tables=[df1.to_html(classes='female'), df2.to_html(classes='male')],
        titles = ['na', 'Codes', 'People'])
        output_file = 'codes_people.xlsx'
    
        session['otpt_file'] = 'tmp/' + output_file
    
    
    def download_df():
        output_file = session.get('otpt_file', None)
        #return output_file
        return send_file(output_file, attachment_filename='output.xlsx', as_attachment=True,mimetype='text/xlsx')