Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Bokeh server callback initiated from Flask application

I am building an app using the Flask-AppBuilder framework, and have successfully embedded a bokeh plot using autoload_server to insert the script src into my html template. At the moment, I have a widget button inside the bokeh app which triggers a python callback to update the plot. What I would like to know is if it is possible to trigger the same behaviour but using a button which sits inside the flask app. It seems to me that this should be possible but I just don't know how to communicate the UI event from a flask button to the bokeh server.

Below is simplified code.

bokeh.py code

Has a callback button to change plot from 'cos' to 'sin'.

import numpy as np
from bokeh.plotting import figure, output_file, show
from bokeh.io import curdoc, reset_output
from bokeh.layouts import column, row
from bokeh.models import Button 

def plotRoutine(input):

    x = np.linspace(0,10)
    if input=='cos':
        y = np.cos(x)
    if input=='sin':
        y = np.sin(x)

    plot = figure(title = input)
    plot.line(x, y)

    return plot

def callback():
    plot = plotRoutine('sin')
    layout.children[1] = plot

plot = plotRoutine('cos')

button = Button(label="Callback button in bokeh server") 
button.on_click(callback) 

layout = column(button, plot)
curdoc().add_root(layout)
curdoc().title = "bokeh"

Flask app

Embeds the bokeh app using bokeh server. I am first running bokeh serve --allow-websocket-connection=localhost:5006 --allow-websocket-connection=localhost:8080 bokeh.py in command prompt to start the bokeh server. Then I start my flask app on localhost:8080.

from flask import render_template, request, g
from flask_appbuilder import ModelView, BaseView, expose, has_access
from bokeh.embed import autoload_server

class Bokeh(BaseView):

    default_view = 'bokeh'

    @expose("/")
    @has_access
    def bokeh(self):
        script = autoload_server(model=None, url="http://localhost:5006/bokeh")
        return self.render_template('bokeh.html', bokeh_script=script)

appbuilder.add_view(Bokeh(), "Bokeh", href="/bokeh/")

Flask bokeh.html template

Has a button that I would like to somehow trigger the callback inside the bokeh.py.

{% extends "appbuilder/base.html" %}
{% block content %}

<script>

    $(document).ready(function () {

        document.getElementById("flaskButton").onclick = function () {

            // CODE HERE TO TRIGGER CALLBACK?

        };

    });

</script>

<div id="bokeh_app">
    {{ bokeh_script|safe }}
</div>

<button id="flaskButton">Callback button in Flask</button>

{% endblock %}
like image 460
GratefulGuest Avatar asked May 08 '17 02:05

GratefulGuest


1 Answers

A quick and dirty way looks to be to right-click on the Bokeh button in your browser and select 'Inspect Element'. You should see the defined onClick function. From there you should be able to provide that same onClick function to your button in your Flask app:

$(document).ready(function () {

    document.getElementById("flaskButton").onclick = [onClick function from Bokeh button];

});

The above only applies if you wish to keep both buttons.

like image 110
Kyle Ingraham Avatar answered Nov 12 '22 13:11

Kyle Ingraham