3
votes

I'm trying to integrate a Bokeh "autoloaded" server into a Flask app where the set of data to load would be chosen by the user on another page.

The ID of this set of data is in the URL (get parameter), and I'm not able to send it from the Flask app to the Bokeh server.

Some example code:

# flask_app.py
import subprocess
import atexit
import subprocess, os

from flask import render_template, render_template_string, Flask

from bokeh.embed import autoload_server
from bokeh.client import pull_session, push_session

app_html = """
<!DOCTYPE html>
<html lang="en">
  <body>
    <div class="bk-root">
      {{ bokeh_script|safe }}
    </div>
  </body>
</html>
"""

app = Flask(__name__)

bokeh_process = subprocess.Popen(
    ['bokeh', 'serve', '--allow-websocket-origin=localhost:5000', 'sample.py'], stdout=subprocess.PIPE)

@atexit.register
def kill_server():
    bokeh_process.kill()

@app.route('/visualization/<int:batchid>')
def visualization(batchid):
    session = pull_session(app_path='/sample')

    # I'd love to do something like that... though it doesn't work :
    session.document.batch_id = batchid
    bokeh_script = autoload_server(None, app_path="/sample", session_id=session.id)
    return render_template_string(app_html, bokeh_script=bokeh_script)

if __name__ == '__main__':
    print("STARTED")
    app.run(debug=True)

and for the bokeh server:

# sample.py
import pandas as pd  
import bokeh  

# ... doesn't work
data = pd.read_csv('batch-%i.csv' % (curdoc().batch_id))

Since autoload_server creates a Javascript snippet, there is no way to use the URL parameters for the Bokeh server to pass this data (along with curdoc().session_context)

So... is there any way to pass arguments to a Bokeh app that way? TYA!

1

1 Answers

2
votes

You can do it by appending to the src attribute of the <script> tag returned from autoload_server. Check out my function appendQuery in the source for this question

def appendQuery( script , key , value) :
    # Pass along the parameter as a query string to the script's src url: TODO this will formally be introduced in next release of Bokeh to avoid this hack
    script_list = script.split("\n")
    idxSrcAttr = 2
    script_list[idxSrcAttr] = script_list[idxSrcAttr][:-1] + "&{}={}\"".format( key , value )
    script = "\n".join(script_list)
    return script

This is methodology is supposed to be formalized in an upcoming Bokeh release according to... https://github.com/bokeh/bokeh/issues/5992#issuecomment-287232101