Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Quick demo embedding a Bokeh chart inside a Flask application

This works in a python 3.6 environment with bokeh and flask installed. To use this you need the following directory structure:

app/
 - templates/
   - hello.html
 - bokeh-slider.py
 - hello.py

After that you need to open two terminals at app/, in the first one you need to run the bokeh server with the command:

bokeh serve ./bokeh-sliders.py --allow-websocket-origin=127.0.0.1:5000

In the second one run the command:

python hello.py

After this the webpage should 'just work' by opening a webpage to http://localhost:5000

''' Present an interactive function explorer with slider widgets.
Scrub the sliders to change the properties of the ``sin`` curve, or
type into the title text box to update the title of the plot.
Use the ``bokeh serve`` command to run the example by executing:
bokeh serve sliders.py
at your command prompt. Then navigate to the URL
http://localhost:5006/sliders
in your browser.
'''
import numpy as np
from bokeh.io import curdoc
from bokeh.layouts import row, widgetbox
from bokeh.models import ColumnDataSource
from bokeh.models.widgets import Slider, TextInput
from bokeh.plotting import figure
# Set up data
N = 200
x = np.linspace(0, 4*np.pi, N)
y = np.sin(x)
source = ColumnDataSource(data=dict(x=x, y=y))
# Set up plot
plot = figure(plot_height=400, plot_width=400, title="my sine wave",
tools="crosshair,pan,reset,save,wheel_zoom",
x_range=[0, 4*np.pi], y_range=[-2.5, 2.5])
plot.line('x', 'y', source=source, line_width=3, line_alpha=0.6)
# Set up widgets
text = TextInput(title="title", value='my sine wave')
offset = Slider(title="offset", value=0.0, start=-5.0, end=5.0, step=0.1)
amplitude = Slider(title="amplitude", value=1.0, start=-5.0, end=5.0)
phase = Slider(title="phase", value=0.0, start=0.0, end=2*np.pi)
freq = Slider(title="frequency", value=1.0, start=0.1, end=5.1)
# Set up callbacks
def update_title(attrname, old, new):
plot.title.text = text.value
text.on_change('value', update_title)
def update_data(attrname, old, new):
# Get the current slider values
a = amplitude.value
b = offset.value
w = phase.value
k = freq.value
# Generate the new curve
x = np.linspace(0, 4*np.pi, N)
y = a*np.sin(k*x + w) + b
source.data = dict(x=x, y=y)
for w in [offset, amplitude, phase, freq]:
w.on_change('value', update_data)
# Set up layouts and add to document
inputs = widgetbox(text, offset, amplitude, phase, freq)
curdoc().add_root(row(inputs, plot, width=800))
curdoc().title = "Sliders"
<html>
<head>
<title>Website</title>
<style>
@import url(http://fonts.googleapis.com/css?family=Amatic+SC:700);
body{
text-align: center;
}
h1{
font-family: 'Amatic SC', cursive;
font-weight: normal;
color: #8ac640;
font-size: 2.5em;
}
</style>
</head>
<body>
<p>Flask embedding Bokeh test</p>
{{ bokS|indent(4)|safe }}
</body>
</html>
from flask import Flask, flash, redirect, render_template, request, session, abort
from bokeh.embed import autoload_server
app = Flask(__name__)
@app.route("/")
def hello():
script=autoload_server(model=None,app_path="/bokeh-sliders",url="http://localhost:5006")
return render_template('hello.html',bokS=script)
if __name__ == "__main__":
app.run()
@wamarobert

This comment has been minimized.

Copy link

@wamarobert wamarobert commented Sep 18, 2017

Hello,
thanks for the help out here. I tried out the code and my socket seems not to be opening with the error below.....

017-09-18 16:37:18,801 Refusing websocket connection from Origin 'http://localhost:5006'; use --allow-websocket-origin=localhost:5006 to permit this; currently we allow origins {'127.0.0.1:5006'}
2017-09-18 16:37:18,802 403 GET

@dmitriidatsenko

This comment has been minimized.

Copy link

@dmitriidatsenko dmitriidatsenko commented Sep 28, 2017

Thank you. Your script helped me alot.

@spyphy

This comment has been minimized.

Copy link

@spyphy spyphy commented Mar 6, 2018

$ python3 hello.py
Traceback (most recent call last):
File "hello.py", line 2, in
from bokeh.embed import autoload_server
ImportError: cannot import name 'autoload_server'

@coderfever

This comment has been minimized.

Copy link

@coderfever coderfever commented Mar 28, 2018

@spyphy
I used Bokeh 0.12.14, which gave me the same 'autoload_server' error. Going through the documentation, I replaced hello.py to use "server_document":

from flask import Flask, flash, redirect, render_template, request, session, abort
from bokeh.embed import server_document
# import bokeh
app = Flask(__name__)

@app.route("/")
def hello():
    # script=server_document(model=None,app_path="/bokeh-sliders",url="http://localhost:5006")
    script=server_document("http://localhost:5006/bokeh-sliders")
    print(script)
    return render_template('hello.html',bokS=script)

if __name__ == "__main__":
    app.run()
@sameerCoder

This comment has been minimized.

Copy link

@sameerCoder sameerCoder commented May 29, 2020

Hi,
Can you help me in this bokeh dynamic plot , where i am missing the stuff ,
I am getting bokeh plot in flask embedded in webpage but it is static not dynamic .,
Do i have to write function for current document / modify doc . link is below there u can find details.
https://stackoverflow.com/questions/62077389/bokeh-embedded-plot-not-acting-dynamic-in-flask-app-with-no-error
Thankyou.

@Wildcarde

This comment has been minimized.

Copy link
Owner Author

@Wildcarde Wildcarde commented Jun 8, 2020

@sameerCoder i don't actually work with this code like... ever. When I was working on this I was just stitching something together for my wife's data science class so they had a building block to work from and honestly had no idea people were commenting on this I only recently changed my email notifications and started getting comments on my gists.

however a quick glance at your SO post makes me suspect bokeh isn't being run as an active server like i have here. The aboves structure is:
bokeh app running free standing
flask app running free standing, it generates a unique id number for the script on each connection to the route / so that individual users have independent instances of the bokeh app.

This setup requires running 2 entirely separate processes, rather than embedding all of the code into a single script.

These days i'd probably make this more complicated and use something like supervisord to launch the independent scripts (or put them in their own docker containers and use compose).

@Wildcarde

This comment has been minimized.

Copy link
Owner Author

@Wildcarde Wildcarde commented Jun 8, 2020

To anybody else that has asked a question on this in the past, sorry I didn't follow up with you. I legit had no idea people were commenting on this post. I'm guessing several years later you no longer need help puzzling this out; and i suspect that things have changed significantly in the mean time. Sorry!

@sameerCoder

This comment has been minimized.

Copy link

@sameerCoder sameerCoder commented Jun 9, 2020

@Wildcarde
Hi,
Thanks for reply.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment