Bokeh: Генерируйте граф на стороне сервера, обновляйте граф из JS на стороне клиента (изменяйте источник данных, оси ...)
Я только что опробовал Bokeh на сайте Django. Там много прекрасных руководств и очень легко сделать быстрый пример. Например, у меня есть представление Django, которое предлагает что-то вроде:
...
# This is part of a broader Django view, simply adding a graph to it.
# Fetch the x and y data for a histogram using a custom function.
# It takes a queryset, a field in that queryset and returns, two lists one
# containing the unique values that some field took on and the second containing
# the count of times it took on that value.
(values, frequency) = FrequencyData(some_queryset, "some field")
p = figure(height=350,
x_axis_label="Count of Players",
y_axis_label="Number of Events",
background_fill_alpha=0,
border_fill_alpha=0,
tools="pan,wheel_zoom,box_zoom,save,reset")
p.xaxis.ticker = values
p.yaxis.ticker = list(range(max(frequency) + 1))
p.toolbar.logo = None
p.vbar(x=values, top=frequency, width=0.9)
p.y_range.start = 0
graph_script, graph_div = components(p)
context.update({"graph_script": graph_script,"graph_div": graph_div})
...
Тогда в шаблоне Django я просто имею:
{{ graph_div | safe }}
{{ graph_script| safe }}
И у меня есть прекрасная гистограмма данных, которые иначе представлены в таблице на этом представлении. Мне это нравится.
Теперь это же представление, как и многие другие, имеет кучу настроек для фильтрации данных, в первую очередь, и кнопку обновления. Кнопка обновления запускает AJAX-обратный вызов представления, которое должным образом передает дату в JSON, а таблица и все остальное на странице обновляется в JS, чтобы отразить новые данные. Все довольно стандартно.
Увы, график не обновляется. И это не ново, я могу найти много вопросов и ответов по этому поводу. НО, дело в том, что ни один из них пока не принес мне удовлетворения, и я исчерпал все возможные ответы. Я просмотрел документацию Bokeh и тоже пока не нашел радости.
Итак, чтобы разложить по полочкам уже имеющиеся на столе решения, которые не устраивают меня в полной мере:
Запустите сервер Bokeh. Это было бы параллельно с сервисом Django UWSGI, и у него есть некоторые преимущества, но здесь это излишество IMHO. Я понимаю, что он взаимодействует с помощью Tornado (и веб-сокетов) с JS на стороне клиента (включенным в
{{ graph_script| safe }}и его зависимостями из CDN, конечно, согласно всем документам). Но именно мое приложение Django получает AJAX-запрос на новые данные, и даже если бы я захотел добавить эту часть инфраструктуры (а я могу сделать это позже, конечно, из-за других преимуществ), я застрял с приложением Django, сообщающим серверу bokeh, что на графике есть новые данные. Поэтому им тоже нужно общаться.Использую BokehJS. Увы, это выглядит как смена парадигмы на построение графа на стороне клиента. Более привлекательным и запасным вариантом действительно является то, что я просто отправляю данные на сторону клиента (через шаблон, отображаемый при загрузке страницы, и AJAX после этого при обновлении) и отображаю граф на стороне клиента. Минусами являются предупреждение в справке (что это находится в разработке и может измениться), а также разочарование от того, что не удалось найти более простое решение, которое, похоже, соответствует стандартным демонстрациям и учебникам Bokeh.
.Настройка графа для использования AjaxDataSource. To be honest I'm not quite sure how to integrate that with the sample above yet, but haven't researched this deeply as it's unsatisfying, works on its own Ajax call and a polling interval. I already do an Ajax call, on demand when a user changes settings and asks for an update, and I'd like the graph to source the data from the return of my call, not its own. Basically, I'm plugging a graph here into an existing context with its modus operandi in place.
Итак, как выглядит мое идеальное решение? Ну, в моем представлении Python выше, я добавляю данные:
# as above ... except:
context.update({"graph_script": graph_script,"graph_div": graph_div, "values": values, "frequency": frequency})
и затем на стороне клиента в JavaScript, когда я получаю данные таблицы и обрабатываю их для обновления таблицы, у меня также есть способ сказать "graph_div" что-то вроде: "Эй, у меня есть новые данные x и y для вас и конфигурации оси".
Короче говоря, немного BokehJS (возможность обращаться к графу на стороне клиента и обновлять его) и немного стандартного Bokeh (генерация графа на стороне сервера для первой загрузки страницы).
Конечно, для этого нужно, чтобы graph_script (создаваемый bokeh.embed.components) содержал имя (предоставляемое компонентами) для объекта графа, который раскрывает BokehJS-подобный интерфейс для графа в JS.
Я могу заглянуть в graph_div и увидеть, что ему даны id и data-root-id:
<div class="bk-root" id="ce45dc38-0977-4d2c-a8ae-033dafad5fc8" data-root-id="1078">
, похоже, назначается Bokeh, конечно, и необходим для BokehJS, чтобы найти div, я полагаю. Я также могу посмотреть на graph_script и увидеть, что он встраивает в корень две переменные docs_json и render_items, а также зайти в отладчик браузера, проинспектировать и увидеть, что есть хороший глобальный объект Bokeh вполне доступный, что дает огромную надежду, что он может быть использован для поставки новых данных и конфигурации осей в JS к существующему графику Bokeh, когда он прибывает через наш собственный вызов Ajax (который доставляет больше вещей).
Подозреваю, что если я найду здесь решение, или кто-то поможет мне его найти, это будет стоить небольшого учебника, который я, возможно, напишу! ;-)
Я использую ваш блог для поиска ответа с помощью json запроса в django. Моя веб-страница: bokeh.traimaocv.fr/index/slider слайдер посылает запрос на сервер django и получает данные x и y с помощью json