Update:
I found the original post for this question:
https://groups.google.com/a/continuum.io/forum/#!topic/bokeh/O6eccziL1lM
as well as the corresponding server example:
https://demo.bokehplots.com/apps/export_csv
The reason the above doesn’t work for us is that our data contains strings with commas, so the simple formula for generating csv’s by hand falls over. Pandas have finely honed the ability to save basically anything to csv, and I want to piggyback off of that capability rather than reimplement it in javascript. I’ve tried to combine the linked savecsv example with this SO answer:
to base64 encode the csv text from pandas, then insert the base64 string into javascript code and use a CustomJS callback. Here’s the relevant Python bit (full file linked below):
data = dataframe.iloc[selection]
print(f’I got your df right here! {data.shape}’)
csv = data.to_csv()
b64 = base64.b64encode(csv.encode()).decode() # str → bytes → b64 → str
jscode = f"""
-
var link = document.createElement("a");*
-
link.href = "data:text/csv;base64,{b64}";*
-
link.download = "selected_data.csv";*
-
link.target = "_blank";*
-
link.style.visibility = "hidden";*
-
console.log("saving selected data:");*
-
console.log("{b64}");*
-
link.dispatchEvent(new MouseEvent("click"));*
- “”"*
print('b64 encoded: ', b64)
return CustomJS(code=jscode)
Now the problem I’m facing is that it seems I can’t update the button’s CustomJS callback: calls to button.js_on_click() once the plot is generated appear to have no effect on the javascript side. Here is the javascript console log after clicking download (with no selection), selecting, and then clicking download again:
saving selected data: bokeh.min.js:9:9
LHgseSx1c2VmdWwK bokeh.min.js:10:9
Navigated to data:text/csv;base64,LHgseSx1c2VmdWwK
saving selected data: bokeh.min.js:9:9
LHgseSx1c2VmdWwK bokeh.min.js:10:9
Navigated to data:text/csv;base64,LHgseSx1c2VmdWwK
Meanwhile, the Python side shows that the b64 string in the CustomJS callback is getting updated:
$ python minimal_example.py
WARNING:bokeh.server.util:Host wildcard ‘*’ will allow connections originating from multiple (or possibly all) hostnames or IPs. Use non-wildcard values to restrict access explicitly
I got your df right here! (0, 3)
b64 encoded: LHgseSx1c2VmdWwK
I got your df right here! (4, 3)
b64 encoded: LHgseSx1c2VmdWwKNDMsMC42OTAyMDIyNDQ2NjgzNDA2LDAuOTg5Mjg5Mjg3MDg1OTI1Niw1MQo4OSwwLjU3MjIzMzk2OTUyNDQwNjMsMC44OTM5MjIwMDA2NjYwMjc5LDEKNDAsMC42NTM1NTIwMTQ1MDU1NjUyLDAuODc5MTk4OTU3NDg5MDcyMSw3MAo1MywwLjY1MjQ4MjM3NDAzNjIwMTEsMC45NjM3ODY5NzU0NzEzNDMyLDc4Cg==
But I guess the CustomJS is not being added to the JS side. Is this a bug or a feature? Does anyone have any suggestions for how to update a javascript callback from Python, or even just the corresponding link href?
Thanks!
Juan.
… [1] attempt to save csv of selection from bokeh plot (not working) · GitHub