Боке - Модели должны принадлежать только одному документу [ошибка] - PullRequest
0 голосов
/ 01 мая 2018

Попытка создать панель с несколькими страницами, используя комбинацию Flask / Bokeh. Код, который я использую для основного файла (test.py), собирает (импортирует) все файлы, соответствующие страницам панели инструментов.

# test.py
from page1 import Page1

app = Flask(__name__)
app.config.from_envvar('FLASKR_SETTINGS', silent=True)


class Dashboard(object):
    def __init__(self, *pages):
        self._pages = [page(self) for page in pages]

    def __call__(self, doc):
        tabs = []
        for page in self._pages:
            tabs.append(Panel(child=page.layout, title=page.title))
        doc.add_root(Tabs(tabs=tabs))


bkapp = Application(FunctionHandler(Dashboard(Page1)))

Цель состоит в том, чтобы определить каждую страницу панели мониторинга в своем собственном файле, который, в конечном итоге, импортируется в основной файл (test.py) и обслуживается веб-сервером (например, gunicorn).

# page1.py                                                                                                                                                 from bokeh.models.widgets import Select
from bokeh.layouts import column, gridplot, widgetbox, layout, row

class Page(object):

    title = "Override in subclass"

    def __init__(self, dashboard):
        self._dash = dashboard
        self._layout = None

    @property
    def layout(self):

        if self._layout is None:
            self._layout = self._make_layout()
        return self._layout

    def _make_layout(self):
        raise NotImplementedError("subclasses must define")


class Page1(Page):
    title = "Page1"

    def _make_layout(self):
        self.sim_prod = Select(title="Selection:",
                               value="Yes",
                               options=["Yes", "No"]
                               )
        self.x = row(self.sim_prod)
        self.layout1 = layout([ [self.x] ], sizing_mode='scale_width')
        return self.layout1

    def some_callback(self, attr, old, new):
    # to be defined later
        pass

Виджет (в данном случае Select) построен и обслуживается правильно (см. Рисунок), но при попытке перезагрузить страницу генерируется ошибка:

Ошибка:

   raise RuntimeError("Models must be owned by only a single document, %r is already in a doc" % (self))
RuntimeError: Models must be owned by only a single document, WidgetBox(id='04f8b890-e3ca-48d9-954d-c33b96e80c78', ...) is already in a doc
ERROR:tornado.access:500 GET /bkapp/autoload.js?bokeh-autoload-element=8ca7bf9a-0c4f-462c-97f9-1f6b1a246628&bokeh-app-path=/bkapp&bokeh-absolute-url=http://127.0.0.1:60624/bkapp (127.0.0.1) 233.03ms
[2018-05-01 10:17:20 -0700] [94201] [DEBUG] GET /

enter image description here

Любое предложение, как это исправить, с благодарностью! Я использую Python 3.6 и Bokeh 0.12.15.

Приветствия

1 Ответ

0 голосов
/ 02 мая 2018

В случае, если кто-то столкнется с той же проблемой, при изменении метода layout класса Page, как показано ниже, макет создается заново при каждой перезагрузке страницы.

class Page(object):

    title = "Override in subclass"

    def __init__(self, dashboard):
        self._dash = dashboard
        self._layout = None

    @property
    def layout(self):
        return self._make_layout()

    def _make_layout(self):
        raise NotImplementedError("subclasses must define")
...