download dataframe as csv through Bokeh app

I have a bokeh app along the lines of stock_app.py. My users have requested the ability to get a download of some of the data used in the plots. I’m not too familiar with Flask, but it seems that downloading a file goes something like this (assuming the existence of a DataFrame called “df”):

from flask import Flask, make_response
app = Flask(name)

@app.route(’/download’)
def download():
dfbuffer = StringIO()
df.to_csv(dfbuffer, encoding=‘utf-8’, index=False)
dfbuffer.seek(0)
values = dfbuffer.getvalue()
output = make_response(values)
output.headers[“Content-Disposition”] = ‘download.csv’
output.headers[“Content-type”] = “text/csv”
return output

app.debug = True
app.run()

``

In my naiveté, I tried including a method in my Bokeh app that looks like this (set as a callback on a Button widget):

def download_csv(self, obj, attr, old, new):
dfbuffer = StringIO()
df = self.df
df.to_csv(dfbuffer, encoding=‘utf-8’, index=False)
dfbuffer.seek(0)
values = dfbuffer.getvalue()
output = make_response(values)
output.headers[“Content-Disposition”] = ‘download.csv’
output.headers[“Content-type”] = “text/csv”
return output

``

When I click the button, I get no errors, but also no download, so that’s clearly not the right way to do it. Is there a way to let a user download a csv file through a Bokeh app?

In case anyone comes across this later and wants to know:

I didn’t figure out a way to do this with Flask, so I just added the following Callback to a Button widget.

Callback(
args=dict(objArray=data_source),
code="""
var array = objArray.attributes.data;
var str = ‘’;
var line = ‘’;
objKeys = Object.keys(array)
var placeholder_key = objKeys[0]

        for (var i = 0; i < objKeys.length; i++) {
            var value = objKeys[i] + "";
            line += '"' + value.replace(/"/g, '""') + '",';
        }

        line = line.slice(0, -1);
        str += line + '\\r\\n';

        for (var i = 0; i < array[placeholder_key].length; i++) {
            var line = '';

            for (var j = 0; j < objKeys.length; j++) {
                var index = objKeys[j]
                var value = array[index][i] + "";
                line += '"' + value.replace(/"/g, '""') + '",';
            }
            line = line.slice(0, -1);
            str += line + '\\r\\n';
        }
        window.open("data:text/csv;charset=utf-8," + escape(str));
        """)

``

···

On Thursday, July 30, 2015 at 12:44:40 PM UTC-4, Schaun Wheeler wrote:

I have a bokeh app along the lines of stock_app.py. My users have requested the ability to get a download of some of the data used in the plots. I’m not too familiar with Flask, but it seems that downloading a file goes something like this (assuming the existence of a DataFrame called “df”):

from flask import Flask, make_response
app = Flask(name)

@app.route(’/download’)
def download():
dfbuffer = StringIO()
df.to_csv(dfbuffer, encoding=‘utf-8’, index=False)
dfbuffer.seek(0)
values = dfbuffer.getvalue()
output = make_response(values)
output.headers[“Content-Disposition”] = ‘download.csv’
output.headers[“Content-type”] = “text/csv”
return output

app.debug = True
app.run()

``

In my naiveté, I tried including a method in my Bokeh app that looks like this (set as a callback on a Button widget):

def download_csv(self, obj, attr, old, new):
dfbuffer = StringIO()
df = self.df
df.to_csv(dfbuffer, encoding=‘utf-8’, index=False)
dfbuffer.seek(0)
values = dfbuffer.getvalue()
output = make_response(values)
output.headers[“Content-Disposition”] = ‘download.csv’
output.headers[“Content-type”] = “text/csv”
return output

``

When I click the button, I get no errors, but also no download, so that’s clearly not the right way to do it. Is there a way to let a user download a csv file through a Bokeh app?

Thanks for sharing Schaun.

···

On Mon, Aug 3, 2015 at 8:07 PM, Schaun Wheeler [email protected] wrote:

In case anyone comes across this later and wants to know:

I didn’t figure out a way to do this with Flask, so I just added the following Callback to a Button widget.

Callback(
args=dict(objArray=data_source),
code="""
var array = objArray.attributes.data;
var str = ‘’;
var line = ‘’;
objKeys = Object.keys(array)
var placeholder_key = objKeys[0]

        for (var i = 0; i < objKeys.length; i++) {
            var value = objKeys[i] + "";
            line += '"' + value.replace(/"/g, '""') + '",';
        }

        line = line.slice(0, -1);
        str += line + '\\r\\n';

        for (var i = 0; i < array[placeholder_key].length; i++) {
            var line = '';

            for (var j = 0; j < objKeys.length; j++) {
                var index = objKeys[j]
                var value = array[index][i] + "";
                line += '"' + value.replace(/"/g, '""') + '",';
            }
            line = line.slice(0, -1);
            str += line + '\\r\\n';
        }
        window.open("data:text/csv;charset=utf-8," + escape(str));
        """)

``

On Thursday, July 30, 2015 at 12:44:40 PM UTC-4, Schaun Wheeler wrote:

I have a bokeh app along the lines of stock_app.py. My users have requested the ability to get a download of some of the data used in the plots. I’m not too familiar with Flask, but it seems that downloading a file goes something like this (assuming the existence of a DataFrame called “df”):

from flask import Flask, make_response
app = Flask(name)

@app.route(’/download’)
def download():
dfbuffer = StringIO()
df.to_csv(dfbuffer, encoding=‘utf-8’, index=False)
dfbuffer.seek(0)
values = dfbuffer.getvalue()
output = make_response(values)
output.headers[“Content-Disposition”] = ‘download.csv’
output.headers[“Content-type”] = “text/csv”
return output

app.debug = True
app.run()

``

In my naiveté, I tried including a method in my Bokeh app that looks like this (set as a callback on a Button widget):

def download_csv(self, obj, attr, old, new):
dfbuffer = StringIO()
df = self.df
df.to_csv(dfbuffer, encoding=‘utf-8’, index=False)
dfbuffer.seek(0)
values = dfbuffer.getvalue()
output = make_response(values)
output.headers[“Content-Disposition”] = ‘download.csv’
output.headers[“Content-type”] = “text/csv”
return output

``

When I click the button, I get no errors, but also no download, so that’s clearly not the right way to do it. Is there a way to let a user download a csv file through a Bokeh app?

You received this message because you are subscribed to the Google Groups “Bokeh Discussion - Public” group.

To unsubscribe from this group and stop receiving emails from it, send an email to [email protected].

To post to this group, send email to [email protected].

To view this discussion on the web visit https://groups.google.com/a/continuum.io/d/msgid/bokeh/a9af703b-7c24-4ff4-a87e-96f1eb503360%40continuum.io.

For more options, visit https://groups.google.com/a/continuum.io/d/optout.

Hi Schaun,

Thanks for sharing. The following flask view should work:

from flask import Flask, make_response, Response
app = Flask(name)

@app.route(’/download’)
def download():
dfbuffer = StringIO()
df.to_csv(dfbuffer, encoding=‘utf-8’, index=False)
dfbuffer.seek(0)
values = dfbuffer.getvalue()
return Response(values, mimetype=‘text/csv’)

``

Cheers

Fabio

···

On Monday, August 3, 2015 at 8:07:30 PM UTC+2, Schaun Wheeler wrote:

In case anyone comes across this later and wants to know:

I didn’t figure out a way to do this with Flask, so I just added the following Callback to a Button widget.

Callback(
args=dict(objArray=data_source),
code="""
var array = objArray.attributes.data;
var str = ‘’;
var line = ‘’;
objKeys = Object.keys(array)
var placeholder_key = objKeys[0]

        for (var i = 0; i < objKeys.length; i++) {
            var value = objKeys[i] + "";
            line += '"' + value.replace(/"/g, '""') + '",';
        }

        line = line.slice(0, -1);
        str += line + '\\r\\n';

        for (var i = 0; i < array[placeholder_key].length; i++) {
            var line = '';

            for (var j = 0; j < objKeys.length; j++) {
                var index = objKeys[j]
                var value = array[index][i] + "";
                line += '"' + value.replace(/"/g, '""') + '",';
            }
            line = line.slice(0, -1);
            str += line + '\\r\\n';
        }
        window.open("data:text/csv;charset=utf-8," + escape(str));
        """)

``

On Thursday, July 30, 2015 at 12:44:40 PM UTC-4, Schaun Wheeler wrote:

I have a bokeh app along the lines of stock_app.py. My users have requested the ability to get a download of some of the data used in the plots. I’m not too familiar with Flask, but it seems that downloading a file goes something like this (assuming the existence of a DataFrame called “df”):

from flask import Flask, make_response
app = Flask(name)

@app.route(’/download’)
def download():
dfbuffer = StringIO()
df.to_csv(dfbuffer, encoding=‘utf-8’, index=False)
dfbuffer.seek(0)
values = dfbuffer.getvalue()
output = make_response(values)
output.headers[“Content-Disposition”] = ‘download.csv’
output.headers[“Content-type”] = “text/csv”
return output

app.debug = True
app.run()

``

In my naiveté, I tried including a method in my Bokeh app that looks like this (set as a callback on a Button widget):

def download_csv(self, obj, attr, old, new):
dfbuffer = StringIO()
df = self.df
df.to_csv(dfbuffer, encoding=‘utf-8’, index=False)
dfbuffer.seek(0)
values = dfbuffer.getvalue()
output = make_response(values)
output.headers[“Content-Disposition”] = ‘download.csv’
output.headers[“Content-type”] = “text/csv”
return output

``

When I click the button, I get no errors, but also no download, so that’s clearly not the right way to do it. Is there a way to let a user download a csv file through a Bokeh app?