我做了一个很复杂的Bokeh仪表板。我没有为仪表板定义任何html模板。我只是使用下面的代码服务它。
我的问题是,当使用bokeh.plotting.output_notebook
函数将其嵌入到Jupyter笔记本中时,仪表板看起来非常漂亮。现在,当尝试在Jupyter之外创建和提供仪表板时,它看起来更加丑陋,因为一些呈现漂亮表格的样式表并不存在。我的问题是,如何将外部样式表添加到我的bokeh webapp中。
仪表板代码:
def emb_bokehdash(self, doc, dash_width=1500, dash_height=800):
# Get base data:
df_orig = self._get_base_data_for_vis(unlabeled_name)
unique_labels = list(df_orig.label.unique())
...
# Sentence Selection Controls:
index_text = AutocompleteInput(
title="select sentence index", value=str(candidate_state),
completions=list(df_orig.index.map(lambda idx: str(idx))),
width=control_width
)
index_next = Button(label="next", button_type="primary", width=button_width)
index_back = Button(label="back", button_type="primary", width=button_width)
selection_checkboxes = CheckboxGroup(labels=['unseen', 'random'], active=[])
index_input = row(
widgetbox(index_text, width=control_width+200),
widgetbox(index_next, index_back, width=button_width+40),
selection_checkboxes,
width=info_width
)
... More code defining DOM and wrangling data
layout_ = row(inputs_and_info, plot, height=dash_height)
# initial load of the data
update_selectioninfo_and_plot()
update_selected_info()
# Register title and dashboard with the document:
doc.title = "Smart Feedback Labeler"
doc.add_root(layout_)
仪表板服务器代码:
from bokeh.server.server import Server
from os import getpid
def emb_bokehdash_serve(self, **server_kwargs):
# Route App:
apps = {'/': Application(FunctionHandler(self.bokeh_dashboard))}
# Extract Port (default = 5000):
if "port" not in server_kwargs:
server_kwargs["port"] = 5000
# Find a suitable port to use:
while True:
try:
server = Server(apps, **server_kwargs)
except OSError:
self.logger.info(
f"Port {server_kwargs['port']} already in use, serving to port {server_kwargs['port']+1}"
)
server_kwargs["port"] += 1
else:
break
# We have to defer opening in browser until we start up the server
def show_callback():
for route in apps.keys():
server.show(route)
server.io_loop.add_callback(show_callback)
# Set server address (default is localhost):
address_string = 'localhost'
if server.address is not None and server.address != '':
address_string = server.address
for route in sorted(apps.keys()):
url = "http://%s:%d%s%s" % (address_string, server.port, server.prefix, route)
self.logger.info("Bokeh app running at: %s" % url)
self.logger.info("Starting Bokeh server with process id: %d" % getpid())
if not run_from_ipython():
server.run_until_shutdown() # Doesn't shutdown properly when run from Jupyter Notebook.
else:
server.start()
注意,我无法静态运行此仪表板。
答案 0 :(得分:0)
我没有遇到您的问题,因为我跳过了Jupyter部分并从一开始就构建了一个独立的仪表板。但是,我使用样式表以下列方式自定义仪表板外观及其元素:
templates/index.html
位于:<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>{{ TITLE }}</title> {{ bokeh_css }} {{ bokeh_js }} <style> {% include 'styles.css' %} </style> </head> <body> <div> {{ plot_div|indent(8) }} {{ plot_script|indent(8) }} </body> </html>
templates/styles.css
内,我有自定义css。<widget object>.css_classes = ["<class from templates/styles.css>"]
。它可以是这种分配中的字符串列表。这有意义吗?我希望这会有所帮助。