用django和bokeh绘制实时数据的正确方法

时间:2016-04-24 20:21:09

标签: python django plot bokeh

我在django应用程序中嵌入了散景图。我在django视图中创建绘图并将绘图推送到散景服务器以在我的网页中显示绘图。

#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时,应该更新图。我不确定最好的方法是什么。

在网页上使用计时器现在要求数据是一个好习惯吗?

或者有没有办法从服务器推送更新,以便每个当前连接的客户端都能获得更新?

我会非常感谢每一个提示。

非常感谢。

3 个答案:

答案 0 :(得分:4)

基本上你的问题是浏览器使用请求 - 响应模式:它们发送请求然后立即回复。您有两种选择,定期轮询服务器或某种通知系统。

通知可以是long-polling, i.e. client makes a request and server doesn't respond until there's data, or through websockets or through HTML5 server-side events

现在,问题是这些通知系统没有与传统的Django部署很好地集成,因为它们会导致打开套接字和相应的挂起线程。因此,如果您的网络服务器有10个Django线程,一个带有10个选项卡的浏览器可能会占用所有这些线程。

正在努力改变这一点,但同时,除非你有一个硬实时要求或许多客户,否则只需设置一个计时器并每x秒轮询一次,其中x取决于可接受的延迟。根据数据的存储方式,我可能会设置一个简单的机制,这样服务器每次都不会发送整个数据集,但只有新的数据集或者什么都没有变化返回代码。

例如,在第一次请求时,服务器可能会在响应中放入时间戳或序列号,然后客户端会询问自该时间戳/序列号以来的任何更改。

通知系统以较低的开销为您提供更好的延迟,但部署可能也会更加困难,如果这只是一个供内部使用的应用程序,可能会有点过分。即使使用通知系统,您也需要进行一些仔细的协议设计,以确保不会错过任何内容。

答案 1 :(得分:3)

在我的意见中,可以在你的前端使用类似心跳计时器的东西,每秒钟触发一次数据提取。特别是如果你在后端实现了缓存。

更复杂的版本可以使用django channels之类的内容 通过网络套接字来处理通信。

我想说这取决于项目的成熟度。

答案 2 :(得分:1)

这样的事情对我有用:

#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})

然后在您的散景服务器上使用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)

然后启动你的散景服务器,并允许从django连接

bokeh serve --allow-websocket-origin=127.0.0.1:8000 myapp.py #you can add app2.py too

我使用的是端口8000,因为那是我的django端口,以及views.py上的端口5006,因为它是我的龙卷风端口。

检查课程columndatasource了解更多

希望它有所帮助。