Bokeh callback in Django and Bootstrap

Django is a high-level Python Web framework that enables rapid development and structured design. Bootstrap is a popular CSS framework for developing responsive and mobile-first websites.

The question here is how to construct an interactive Bokeh callback function when using Django and Bootsrap. The enclosed figure shows an example.


The aim is that the user can press buttons "6 ave", "12 ave ", etc. and the figure gets updates interactively, i.e. additional lines are drawn on the top of the figure or removed.

The virtual environment needs to have the Bokeh package. On the terminal window type

$ pip install bokeh

In Django the configuration requires changes to the following places:

  1. file, and
  2. html file.

Changes in

Insert the following code to the file

from bokeh.models.widgets import CheckboxButtonGroup
from bokeh.models import ColumnDataSource, CustomJS
from bokeh.embed import components
from bokeh.plotting import figure
import bokeh.layouts
import pandas as pd

def show_figure(request):

   # df, df1 and df2 contain the data points in DataFrame format
   data = df[..data_columns x_coord and y_coord..]
   data6 = df1[..data_columns x_coord and y_coord..]
   data12 = df2[..data_columns x_coord and y_coord..]
   text = "title of the figure.. "
   x_axis_min = ..minimum of x-axis
   x_axis_max = ..maximum of x-axis

   plot1 = figure(x_axis_type="datetime", title=text,plot_width=400, plot_height=220,toolbar_location=None,x_range=(x_axis_min,x_axis_max))
   plot1.sizing_mode = 'scale_width'
   fig1 = bokeh.plotting.figure()
   fig1.sizing_mode = 'scale_width'
   column = bokeh.layouts.column([plot1, fig1])
   column.sizing_mode = 'scale_width'

   # ColumnDataSource is a mapping between column names and lists of data
   source = ColumnDataSource(data=dict(data))
   solidline = plot1.line(x='x_coord',y='y_coord',source=source,color='olive')
   source6 = ColumnDataSource(data=dict(data6))
   line6 = plot1.line(x='x_coord',y='y_coord',source=source6,color='blue')
   source12 = ColumnDataSource(data=dict(data12))
   line12 = plot1.line(x='x_coord',y='y_coord',source=source12,color='peru')

   # initially additional lines are not visible
   line6.visible = False
   line12.visible = False

   callback = CustomJS(args=dict(line6=line6,line12=line12), code="""
      var active =;
      line6.visible = false;
      line12.visible = false;
      if (active.includes(0)) {
         line6.visible = true;
      if (active.includes(1)) {
         line12.visible = true;

   # CheckBoxButtonGroups creates a row of buttons which use the callback function
   checkbox_group = CheckboxButtonGroup(labels=["6 ave","12 ave"],callback=callback)

   (scriptgp, (divgp,divgp1)) = components((checkbox_group,plot1))

   return render(request = request,
      context = { 'scriptgp':scriptgp,'divgp':divgp,'divgp1':divgp1, })

Here we have defined a procedure show_figure and the html template it renders is page.html.

Changes in page.html

Insert the following code to the header of the page.html file

   <link href="" rel="stylesheet" type="text/css">
   <link href="" rel="stylesheet" type="text/css">
   <link href="" rel="stylesheet" type="text/css">
   <script src=""></script>
   <script src=""></script>
   <script src=""></script>

The body of the html should have the following content

  < div class="container">
   < div class="img-max" >
     {{ divgp | safe }}
     {{ divgp1 | safe }}
     {{ scriptgp | safe }}
   < /div>
  < /div>

Now the interactive figure should be shown on the page.html page.

Back to the main page.