20

I am trying desperately to embed a working bokeh applet into flask, and can't find a proper way to do this. I looked through all the examples, but I can't find one which includes the ability to update the data (best example: the sliders_applet).

If I'm not mistaken, I do need the bokeh-server to be able to change the data (with sliders etc.). Starting the applet this way works, e.g.:

bokeh-server --script sliders_app.py

But I can't find the proper, or at least a working way to embed the sliders_app into flask. And since it should be possible to use multiple applets, it doesn't seem clean to me to specify one single applet at the startup of the bokeh server too..

I would gladly appreciate any help - bokeh looks like a great tool for me.

erip
  • 16,374
  • 11
  • 66
  • 121
lakerz
  • 1,051
  • 3
  • 12
  • 20

2 Answers2

12

The other answer does not describe how to embed a Bokeh server app (it uses components to embed a standalone Bokeh document).

First, you can see lots of live examples hosted at: https://demo.bokeh.org/

For embedding apps there are two usual options:

The latter is usually used like this:

from bokeh.embed import server_document
script = server_document("https://demo.bokeh.org/sliders")

This will return a <script> tag similar to the one below, that you can put in your flask HTML response, wherever you'd like the app to appear:

<script
    src="https://demo.bokeh.org/sliders/autoload.js?bokeh-autoload-element=1000&bokeh-app-path=/sliders&bokeh-absolute-url=https://demo.bokeh.org/sliders"
    id="1000">
</script>

Lastly, it's important to note that by default the Bokeh server opts for a fairly conservative network configuration. You'll need to start the Bokeh server with --allow-websocket-origin command line option set to be whatever host you are embedding the bokeh app into.

bigreddot
  • 33,642
  • 5
  • 69
  • 122
10

EDIT by one one of the core developers of the Bokeh project The information below does not answer the question above. It is categorically impossibly to embed a Bokeh Application by using bokeh.embed.components as described below. components is only capable of embedding standalone documenents (i.e. that do NOT run on a Bokeh server)


An example of embedding bokeh with flask is present on the bokeh github repo.

import flask

from bokeh.embed import components
from bokeh.plotting import figure
from bokeh.resources import INLINE
from bokeh.templates import RESOURCES
from bokeh.util.string import encode_utf8

app = flask.Flask(__name__)

colors = {
    'Black': '#000000',
    'Red':   '#FF0000',
    'Green': '#00FF00',
    'Blue':  '#0000FF',
}


def getitem(obj, item, default):
    if item not in obj:
        return default
    else:
        return obj[item]


@app.route("/")
def polynomial():
    """ Very simple embedding of a polynomial chart"""
    # Grab the inputs arguments from the URL
    # This is automated by the button
    args = flask.request.args

    # Get all the form arguments in the url with defaults
    color = colors[getitem(args, 'color', 'Black')]
    _from = int(getitem(args, '_from', 0))
    to = int(getitem(args, 'to', 10))

    # Create a polynomial line graph
    x = list(range(_from, to + 1))
    fig = figure(title="Polynomial")
    fig.line(x, [i ** 2 for i in x], color=color, line_width=2)

    # Configure resources to include BokehJS inline in the document.
    # For more details see:
    #   http://docs.bokeh.org/en/latest/docs/reference/resources_embedding.html#module-bokeh.resources
    plot_resources = RESOURCES.render(
        js_raw=INLINE.js_raw,
        css_raw=INLINE.css_raw,
        js_files=INLINE.js_files,
        css_files=INLINE.css_files,
    )

    # For more details see:
    #   http://docs.bokeh.org/en/latest/docs/user_guide/embedding.html#components
    script, div = components(fig, INLINE)
    html = flask.render_template(
        'embed.html',
        plot_script=script, plot_div=div, plot_resources=plot_resources,
        color=color, _from=_from, to=to
    )
    return encode_utf8(html)


def main():
    app.debug = True
    app.run()

if __name__ == "__main__":
    main()

Another idea would be to run bokeh-server and your flask web app side-by-side, and load the bokeh-code that way (server-side or via JS or an iframe), but that could be troublesome.

bigreddot
  • 33,642
  • 5
  • 69
  • 122
halflings
  • 1,540
  • 1
  • 13
  • 34
  • 1
    Thank you very much! The problem for me with this example is, that it just creates a new plot with new parameters - not the kind if interactivity I'm looking for, and secondly, it doesn't involve a real bokeh applet - let's use the sliders_app.py example: It's a real bokeh app which works perfectly fine on the bokeh server directly, plus it has the kind of "real interactivity" I'm looking for. I can't find a way to just embed this applet. – lakerz Apr 30 '15 at 09:29
  • 1
    Mmh. Looking at the [bokeh-server code](https://github.com/bokeh/bokeh/blob/master/bokeh/server/start.py) I see that they're doing quite a lot of stuff. The Flask app is instantiated at the end of [app.py](https://github.com/bokeh/bokeh/blob/master/bokeh/server/app.py) but only later (in start.py) modified. Maybe you could reuse that code in ``start.py`` and add your routes to the ``app`` instance? – halflings May 01 '15 at 14:38
  • 1
    That looks interesting, I will look into it, guess it will take me awhile to fully understand. So far I found two other options: (1) Don't use any bokeh controls, instead re-implement the controls myself (e.g. with jQuery). Works fine, but it feels a bit unnecessary, if bokeh itself provides the same functionality. (2) Just embed the bokeh applet url with an iFrame. Looks like it's working fine, but somehow I have a wild guess that the usage of iFrames is not really a good style.. but it is quite some years since I did something for the web, maybe that changed nowadays? – lakerz May 01 '15 at 17:30
  • iframes still make sense in some usecases, and it might be "good enough" especially if you're just using this internally or for a small web app. – halflings May 03 '15 at 18:09
  • Yes, I thought so too, but I came across some more problem with the bokeh controls, for example the sliders don't work with touch interfaces; therefore I decided to use bokeh just for the plots and implement the controls elsewhere. – lakerz May 03 '15 at 18:41
  • 1
    @lakerz: There's a relatively new lib called Spyre that provides something similar to bokeh-server, although it's not necessarily easier to embed. You can have a look here: https://github.com/adamhajari/spyre – halflings May 06 '15 at 13:39
  • Thanks, that looks interesting, I'll see into it. – lakerz May 07 '15 at 08:26
  • 8
    Hey guys, did anyone manage to implement a neat integration of bokeh server with flask? If yes, posting the code as an answer would be very helpful. – multigoodverse Oct 30 '15 at 02:38
  • I can't seem to get your example to work in bokeh 0.11: bokeh.templates became bokeh.core.templates, and there is RESOURCES but a JD_RESOURCES and a CSS_RESOURCES – famargar Feb 02 '17 at 13:19
  • @famargar: This is an old response so that might very well be true. Could you try to find the equivalent in the new version and update the answer accordingly? – halflings Feb 03 '17 at 15:12
  • @famargar: now you just load INLINE: from bokeh.resources import INLINE, and obtain JS resources like this: js_resources = INLINE.render_js(). This change is reflected in my edit, which is currently under peer review. Thanks for pointing me to a helpful example, halflings! – Brian Bartoldson Jul 13 '17 at 21:11
  • @CDspace didn't think your answer should be updated, even though you ask for someone to update your answer two comments above, so my edit failed peer review and someone else will have to try, halflings. – Brian Bartoldson Jul 15 '17 at 06:57