I want to change the way tabs are rendered in a bokeh application embedded within a Flask Application, and cannot seem to find a way to do this with my current schema, which is as follows:
Bokeh is created in create_app(), borrowed from their server embed example:
def create_app():
#------------------IRRELEVANT FLASK APP STUFF--------------------------------
bkapp = Application(FunctionHandler(my_gui))
# This is so that if this app is run using something like "gunicorn -w 4" then
# each process will listen on its own port
sockets, port = bind_sockets("localhost", 0)
app._bokehport = port
def bk_worker():
asyncio.set_event_loop(asyncio.new_event_loop())
bokeh_tornado = BokehTornado({'/bkapp': bkapp},
extra_websocket_origins=["localhost:8000"])
bokeh_http = HTTPServer(bokeh_tornado)
bokeh_http.add_sockets(sockets)
server = BaseServer(IOLoop.current(), bokeh_tornado, bokeh_http)
server.start()
server.io_loop.start()
from threading import Thread
Thread(target=bk_worker).start()
return app
my_gui is a bokeh app, very simplified version here:
def my_gui(doc):
def toggleMakeCallback():
rootLayout = doc.get_model_by_name('rootLayout')
listOfSubLayouts = rootLayout.children
p1 = figure(width=300, height=300)
p1.circle([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], size=20, color="navy", alpha=0.5)
tab1 = TabPanel(child=p1, title="circle")
p2 = figure(width=300, height=300)
p2.line([1, 2, 3, 4, 5], [6, 7, 2, 4, 5], line_width=3, color="navy", alpha=0.5)
tab2 = TabPanel(child=p2, title="line")
tabs = Tabs(tabs=[ tab1, tab2 ])
listOfSubLayouts.append(tabs)
make_piece = Button(label="Make Piece", button_type="success")
make_piece.on_click(toggleMakeCallback)
rootLayout = layout(make_piece, name='rootLayout', sizing_mode="scale_both")
doc.add_root(rootLayout)
return doc
In my Flask application this is how I route to the app.
@main_bp.route('/bokehexample', methods = ['GET', 'POST'])
@login_required
def bokehRoute():
script = server_document('http://localhost:%d/bkapp' % current_app._bokehport,
arguments={"id": unsplitId, "teamId": teamId})
return render_template("embed.html", script=script, template="Flask")
Finally, this is embed.html:
<!DOCTYPE html>
<html lang='en'>
<head>
<link rel="stylesheet" href="{{ url_for('static', filename='css/embed.css') }}">
<title>PeachPortal - Split Pieces</title>
</head>
<body>
{{ script|safe }}
</body>
</html>
An example of a component of end goal CSS to change the tab design would be as follows:
.bk-root .bk-tab {
background-color: grey;
width: 33%;
color: white;
font-style: italic;
font-size: 20px;
}
.bk-root .bk-tabs-header .bk-tab.bk-active{
background-color: white;
color: #2A2B2C;
font-style: normal;
font-weight: bold;
}
.bk-root .bk-tabs-header .bk-tab:hover{
background-color: white;
color: #2A2B2C;
}
I’ve read and tried and failed with several ways of accomplishing custom CSS (the app just renders the default way no matter what I try):
- Adding this css directly in a
<style></style>
tag in the head of embed.html - Adding this css into the embed.css file referenced in the head of embed.html
- Adding this css in the head of embed.html with a django
{%include customcss.css%}
- Adding a div in my_gui which contains tags
- Adding a css class such as
css_classes =['custom_tab_bokeh']
to my tabs, then having those classes in the head, the div, or the css
I’ve seen another example using curstate, which I don’t know how to use in an app context.
I am hoping somebody has successfully changed the CSS for a Bokeh widget using this schema or something similar.
Thank you.