Каков наилучший способ реализовать принудительное обновление страницы с помощью Flask?
Фон
У меня есть большое количество полей, которые будут обновлять реальное время от внешнего процесса. Я хотел бы периодически обновлять размещенные страницы Flask, чтобы показать подключенным пользователям любые изменения. В идеале, вся страница не обновлялась, это было жалобой на подобную систему, а просто обновляло несколько полей на странице.
Текущее направление
Мои текущие мысли - использовать, возможно, использовать JavaScript, чтобы справиться с этим, но я не уверен, что это возможно даже при использовании Flask.
Есть ли способ с Flask или сторонним модулем для выполнения этого?
Дополнительная информация
Данные будут обновляться с использованием различных сокетов и последовательных портов. Каждый интерфейс будет работать в своем потоке и обновлять общую память. Обратите внимание, что Flask/web-интерфейс имеет запись только для чтения в общую память, которая может быть обновлена другими потоками.
Общий пул клиентов не должен превышать 20 человек. Это веб-интерфейс к тестовой системе, и в общем случае к нему будет подключено только 1-5 человек в любой момент времени.
Ответы
Ответ 1
Чтобы не обновлять всю страницу, вы хотите использовать то, что называется AJAX. Похоже, что это легко реализовать в фляге.
Поскольку вы хотите, чтобы это происходило периодически, вам нужно вызвать функции AJAX из функции timer в javascript.
Это означает, что вы просто поместите 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
Ответ 2
Я думаю, что самый простой способ сделать это - использовать javascript, как вы уже указываете в своем вопросе. В этом случае Flask будет просто доставлять HTML-документ, содержащий код javascript, который будет выполняться браузером, поэтому я не понимаю, почему это может вызвать проблемы с Flask. В этой странице, я нашел несколько примеров, используя различные комбинации, такие как использование таймера (который, кажется, то, что вы ищете).
Ответ 3
Нет. Ну, как ничто в стороне от Flask, это сделало бы это проще, чем другие решения. SO имеет некоторый достойный материал на внедрении кометных серверов в Python.
Как вы упомянули, вы можете использовать JavaScript для опроса сервера для новых данных. Это может быть сложно для вашего сервера, хотя, если у вас много пользователей. Открытие параллельных TCP-соединений довольно дорого. Это также означает, что ваш пользовательский интерфейс может выглядеть слегка рывком, потому что все будет обновляться каждую секунду или около того, а не когда новые данные попадают на сервер.
Учитывая это, Flask отлично подходит для этого второго выбора, потому что так легко подключать функции ответа к отдельным URL-адресам. Главное отметить, что вам следует выполнять функции, которые сильно блокируют ввод-вывод. Долгосрочные функции захватят все приложение.
Скажем, у вас есть два температурных датчика, и вы используете 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);
Ответ 4
Один из способов добиться этого - в 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>