背景
我有大量的字段将从外部进程实时更新。我想定期更新Flask托管页面,以向连接的用户显示任何更改。理想情况下,整个页面不会刷新,这是对类似系统的抱怨,而只是更新页面上的许多字段。
当前方向
我目前的想法是使用可能使用JavaScript来处理这个问题,但我不确定在使用Flask时是否可行。
有没有办法使用Flask或第三方模块来实现这一目标?
其他信息
将使用各种套接字和串行端口更新数据。每个接口都将在其自己的线程中运行并更新共享内存。请注意,Flask / Web界面对共享内存具有只读写入,可由其他线程更新。
总客户端池不应超过20人。这是测试系统的Web界面,通常在任何给定时间只有1-5人连接到它。
答案 0 :(得分:17)
要避免刷新整个页面,您要使用所谓的AJAX。看起来这很容易implement in flask。
由于您希望它定期发生,您需要在javascript中从timer函数调用您的AJAX函数。
这意味着您只需将烧瓶页面中的javascript放入计时器调用中即可。
这里大概是javascript的样子:
setInterval( //Periodically
function()
{
$.getJSON( //Get some values from the server
$SCRIPT_ROOT + '/get_values', // At this URL
{}, // With no extra parameters
function(data) // And when you get a response
{
$("#result").text(data.result); // Write the results into the
// #result element
});
},
500); // And do it every 500ms
答案 1 :(得分:3)
我认为最简单的方法是使用你在问题中建议的javascript。在这种情况下,Flask只是提供一个HTML文档,其中包含一些浏览器要执行的javascript代码,所以我不明白为什么这会给Flask带来任何问题。在this page中,我发现了一些使用不同组合的示例,例如使用计时器(这似乎是您正在寻找的)。
答案 2 :(得分:2)
没有。好吧,至少在Flask方面没有什么能比其他解决方案更容易。在implementing comet servers in Python上有一些不错的材料。
正如您所提到的,您可以使用JavaScript轮询服务器以获取新数据。如果您有很多用户,那么您的服务器很难管理。打开并发TCP连接相当昂贵。这也意味着您的UI可能看起来有些不稳定,因为事情会每隔一秒左右更新一次,而不是在新数据到达服务器时。
考虑到这一点,Flask非常适合第二种选择,因为将响应函数附加到各个URL非常容易。需要注意的主要事项是你应该在I / O上严重阻塞的功能。长时间运行的功能将占用整个应用程序。
假设您有两个温度计和温度计。你正在使用jQuery。
@app.route('/gauge/<int:gauge_id>')
def gauge_temp(gauge_id):
temp = temp_from_db(gauge_id) #implement this yourself
return dict(temp=temp, gauge_id=gauge_id)
在JavaScript文件中,您可以使用当前温度每分钟更新DOM元素的功能。这段代码应该让您对可以构建到实际实现中的内容有所了解:
function updateTemp(gauge_id, selector) {
$.getJSON('/gauge/' + gauge_id, function(data){
$(selector).text = response.temp;
})
}
setInterval('updateTemp(1, "#gauge-1")', 1000 * 60);
setInterval('updateTemp(2, "#gauge-2")', 1000 * 60);
答案 3 :(得分:0)
实现这一目标的一种方法是使用 flask-socketio 在Flask中通过WebSockets实现。我在示例中使用 APScheduler 作为后台进程,但任何后台进程都可以。这会每4秒更新一次网页价格:
from flask import Flask, render_template
from apscheduler.schedulers.background import BackgroundScheduler
from flask_socketio import SocketIO, emit
app = Flask(__name__)
socketio = SocketIO(app)
#defines the job
def job():
new_price = get_new_price();
#job emits on websocket
socketio.emit('price update',new_price, broadcast=True)
#schedule job
scheduler = BackgroundScheduler()
running_job = scheduler.add_job(job, 'interval', seconds=4, max_instances=1)
scheduler.start()
@app.route('/')
def index():
return render_template('index.html')
if __name__ == '__main__':
socketio.run(app, host='0.0.0.0')
然后 index.html 模板是:
<!DOCTYPE HTML>
<html>
<head>
<title>WebSockets Example</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/socket.io/1.3.6/socket.io.min.js"></script>
<script type="text/javascript" charset="utf-8">
$(document).ready(function(){
var socket = io.connect('http://' + document.domain + ':' + location.port);
socket.on('connect', function() {
socket.emit('am up', {data: 'I\'m connected!'});
});
//listens to 'price update' message on socket
socket.on('price update', function(msg) {
$('#price_info').text(msg)
});
});
</script>
</head>
<body>
<div id="price_info"></div>
</body>
</html>