Правильный способ записи живых данных с помощью django и bokeh
У меня есть сюжет bokeh, встроенный в приложение django. Я создаю сюжет в представлении django и нажимаю сюжет на сервер bokeh, чтобы показать сюжет на моей веб-странице.
#view.py
def view_plot(request):
f=figure()
f.plot(#some data#)
session = push_session(curdoc())
context = {'script': autoload_server(f, session_id=session.id)}
return render_to_response('plot.html', context=context)
Все работает неплохо. Теперь я хочу сделать живой сюжет, каждый раз, когда создается новый DB-Entry, сюжет должен быть обновлен. Я не уверен, что это лучший способ.
Хорошо ли использовать таймер на веб-странице для запроса данных?
Или есть способ нажать кнопку обновления на сервере так, чтобы каждый подключенный к клиенту клиент получил обновление графика?
Я был бы очень благодарен за каждый намек.
Большое спасибо.
Ответы
Ответ 1
В основном ваша проблема заключается в том, что браузеры используют шаблон запроса-ответа: они отправляют запрос и сразу же возвращают ответ. У вас есть два варианта: периодически опроса сервера или какой-либо системы уведомлений.
Уведомления могут быть длительным опросом, то есть клиент делает запрос, а сервер не отвечает до тех пор, пока не появятся данные или через веб-сайты или через серверные события HTML5.
Теперь дело в том, что эти системы уведомлений не слишком хорошо интегрируются с традиционным развертыванием Django, поскольку они приводят к открытому сокету и соответствующему зависанию потока. Поэтому, если ваш веб-сервер имеет 10 потоков Django, один браузер с 10 вкладками может связать все их.
В настоящее время ведется работа по его изменению, но в то же время, если у вас нет жесткого требования в реальном времени или большого количества клиентов, просто установите таймер и опробуйте каждые x секунд, где x зависит от того, какая латентность приемлема. В зависимости от того, как хранятся ваши данные, я бы, вероятно, поставил простой механизм, чтобы сервер не отправлял весь набор данных каждый раз, а только то, что новый или не переносимый код возврата.
Например, по первому запросу сервер может помещать в ответ метку времени или серийный номер, а затем клиент запрашивает любые изменения с момента времени/серийного номера.
Система уведомлений дает вам лучшую задержку с более низкими накладными расходами, но, вероятно, ее также будет сложнее развернуть, и, вероятно, она будет чрезмерной, если это всего лишь приложение для внутреннего использования. Даже с системой уведомлений вам нужно сделать тщательный протокол, чтобы не пропустить что-то.
Ответ 2
По моему мнению, хорошо использовать что-то вроде таймера сердечного ритма в вашем интерфейсе, который запускает выборку данных каждую секунду или около того. Особенно, если вы выполнили кэширование на бэкэнд.
Более сложная версия может использовать что-то вроде каналы django
для обработки связи через веб-сокеты.
Я бы сказал, это зависит от зрелости проекта.
Ответ 3
Что-то вроде этого сработало для меня:
#views.py
from bokeh.plotting import figure, curdoc
from bokeh.client import pull_session
def my_line_chart(request):
session = pull_session(url = "http://localhost:5006/myapp")
bokeh_script=autoload_server(None,url = "http://localhost:5006/myapp", session_id= session.id)
return render(request, u'line_charts.html', {u'the_script': bokeh_script})
Затем на сервере bokeh используйте source.stream()
#myapp
'''
everything else here
'''
def update():
new_data = qu() #qu is the newdata to be updated
source.stream(new_data, rollover = 60)
print(source.data) #if you want to see new data
curdoc().add_root(p)
curdoc().add_periodic_callback(update,10000)
затем запустите свой сервер bokeh и разрешите соединение с django, как
bokeh serve --allow-websocket-origin=127.0.0.1:8000 myapp.py #you can add app2.py too
Я использовал порт 8000, потому что это мой порт django и порт 5006 на views.py, потому что это мой порт торнадо.
Проверить класс columndatasource для более
Надеюсь, что это поможет.