Hi all,
I need assistance with including a custom HTML template in the following example app which is embedded in a Tornado server. I am trying to insert a line of javascript to prompt the user if he/she navigates away from the page.
When I had a prefix to the URL in the following line of code in embed.py:
server.io_loop.add_callback(view, "http://localhost:5006/SatProd)
My custom template does not load which contains the javascript code to cause a dialog prompt. If I leave the prefix off and only use “http://localhost:5006/”, then my custom template is loaded correctly.
The app structure is as follows:
-
Boke_test_app
-
SatProd
-
templates
- index.html
-
main.py
-
init.py
-
-
embed.py
-
embed.py
from jinja2 import Environment, FileSystemLoader
from tornado.web import RequestHandler
from bokeh.embed import server_document
from bokeh.server.server import Server
import SatProd.main
env = Environment(loader=FileSystemLoader('./SatProd/templates'))
class IndexHandler(RequestHandler):
def get(self):
template = env.get_template('index.html')
script = server_document('http://localhost:5006/SatProd')
self.write(template.render(script=script, template="Tornado"))
# Setting num_procs here means we can't touch the IOLoop before now, we must
# let Server handle that. If you need to explicitly handle IOLoops then you
# will need to use the lower level BaseServer class.
# The `static/` end point is reserved for Bokeh resources, as specified in
# bokeh.server.urls. In order to make your own end point for static resources,
# add the following to the `extra_patterns` argument, replacing `DIR` with the desired directory.
# (r'/DIR/(.*)', StaticFileHandler, {'path': os.path.normpath(os.path.dirname(__file__) + '/DIR')})
server = Server({'/SatProd': SatProd.main.bkapp}, num_procs=1, extra_patterns=[('/', IndexHandler)])
server.start()
if __name__ == '__main__':
from bokeh.util.browser import view
print('Opening Tornado app with embedded Bokeh application on http://localhost:5006/')
server.io_loop.add_callback(view, "http://localhost:5006/")
#server.io_loop.add_callback(view, "http://localhost:5006/SatProd")
server.io_loop.start()
main.py
from bokeh.layouts import column
from bokeh.models import ColumnDataSource, Slider
from bokeh.plotting import figure
from bokeh.sampledata.sea_surface_temperature import sea_surface_temperature
import panel as pn
def bkapp(doc):
df = sea_surface_temperature.copy()
source = ColumnDataSource(data=df)
plot = figure(x_axis_type='datetime', y_range=(0, 25), y_axis_label='Temperature (Celsius)',
title="Sea Surface Temperature at 43.18, -70.43")
plot.line('time', 'temperature', source=source)
def callback(attr, old, new):
if new == 0:
data = df
else:
data = df.rolling(f"{new}D").mean()
source.data = ColumnDataSource.from_df(data)
slider = Slider(start=0, end=30, value=0, step=1, title="Smoothing by N Days")
slider.on_change('value', callback)
_col = pn.pane.Bokeh(column(slider, plot))
#doc.add_root(column(slider, plot))
_col.server_doc(doc=doc, title='SatProd Tool')
#doc.theme = Theme(filename="theme.yaml")
if __name__ == "__main__":
pass
index.html
<!DOCTYPE html>
<html lang="en">
{% block head %}
<head>
{% block inner_head %}
<meta charset="utf-8">
<title>{% block title %}{{ title | e if title else "Bokeh Plot" }}{% endblock %}</title>
<script> window.onbeforeunload = function() {return ""};</script>
{% block preamble %}{% endblock %}
{% block resources %}
{% block css_resources %}
{{ bokeh_css | indent(8) if bokeh_css }}
{% endblock %}
{% block js_resources %}
{{ bokeh_js | indent(8) if bokeh_js }}
{% endblock %}
{% endblock %}
{% block postamble %}{% endblock %}
{% endblock %}
</head>
{% endblock %}
{% block body %}
<body>
{% block inner_body %}
{% block contents %}
{% for doc in docs %}
{{ embed(doc) if doc.elementid }}
{% for root in doc.roots %}
{{ embed(root) | indent(10) }}
{% endfor %}
{% endfor %}
{% endblock %}
{{ script | indent(8) }}
{% endblock %}
</body>
{% endblock %}
</html>