Hi everyone,
first, thanks for this great project and helpful community!
I’m
working on a small flask app which renders a few templates and embeds interactive bokeh plots with widgets from bokeh serve plot (which is why
I can’t use components, which so far only give me plots without widget responses). I can get the template to render both locally and on Heroku,
however on Heroku the plots (scripts from autoload_server()) are not displaying, and no error is generated anywhere.
This is where I suspect the root of the problem, although I’m mentally stuck in solving it:
When
running locally, debugging with firebug etc. shows that the page source
looks like desired according to the template, with the {{ script | safe
}} embed looking like this:
<script
src="http://127.0.0.1:5006/plot/autoload.js?bokeh-autoload-element=d2af1a37-1349-4b12-a15e-23610fe1d7f8"
id="d2af1a37-1349-4b12-a15e-23610fe1d7f8"
data-bokeh-model-id=""
data-bokeh-doc-id=""
></script>
``
which when inspecting the html shows a generated “div class=‘bk-root’ " followed by two links to bokeh and bokeh widget min.css - which is the expected behaviour, I guess.
The same source code on Heroku then does not generate the “div class=‘bk-root’ " etc, but rather simply gets embedded into the page in its raw text form.
I think that for some reason there is some missing link between script and “div”, where the browser looks at the src=”” attrib and then on the users local machine for the bokeh server and not in the VM on heroku.
This is what I do:
The relevant part in the app currently looks like this:
@app.route(“/plot”)
def plot():
script = autoload_server(model=None, app_path=“/plot”, url=“http://127.0.0.1:5006”)
return render_template(
“plot.html”,
script = script
)
``
and the template:
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Plot Title</title>
<link
href="https://cdn.pydata.org/bokeh/release/bokeh-0.12.2.min.css"
rel="stylesheet" type="text/css">
<link
href="https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.2.min.css"
rel="stylesheet" type="text/css">
<script src="https://cdn.pydata.org/bokeh/release/bokeh-0.12.2.min.js"></script>
<script src="https://cdn.pydata.org/bokeh/release/bokeh-widgets-0.12.2.min.js"></script>
<link rel=stylesheet type=text/css href="static/css/style.css">
</head>
<div class=page>
<body>
some text and h and p tags
{{ script | safe }}
</body>
</div>
</html>
``
I start both processes with a Procfile looking like that:
web: gunicorn app:app
bokeh: bokeh serve plot.py --port=5006 --host=127.0.0.1:5006 --address=127.0.0.1 --allow-websocket-origin=127.0.0.1:5006 --allow-websocket-origin=0.0.0.0:5000 --host=localhost:5006
``
Both processes run on the same dyno (virtual machine) and according to Heroku support are able to communicate - but only the web app process is allowed to communicate with the outside world, any interprocess communication would have to happen within the VM (dyno):
You should be able to bind to localhost, does using
127.0.0.1
as the binding IP and also the request address work? Alternatively might you be able to try a UNIX socket? That is quite common for IPC on-dyno. Depending on the clients and servers used it’s often just a matter of updating the listen URL and request URL.
So i think my question would be: How do I tell flask to connect to the bokeh server and to generate the div directly (still providing widget interactivity and reading data from the server), instead of relaying the unconverted script tag to the end browser?
I hope I provided all relevant information, if not I’ll try to provide it as requested.
Thanks for your help!
Christopher