Каков наилучший способ принудительного обновления страницы с помощью Flask? - PullRequest
21 голосов
/ 12 декабря 2011

Фон
У меня есть большое количество полей, которые будут обновляться в реальном времени из внешнего процесса.Я хотел бы периодически обновлять страницы, размещенные на Flask, чтобы показать подключенным пользователям любые измененияВ идеале вся страница не будет обновляться, это была жалоба аналогичной системы, а скорее просто обновить несколько полей на странице.

Текущее направление
Мои нынешние мысли таковыиспользовать, возможно, использовать JavaScript, чтобы справиться с этим, но я не уверен, возможно ли это даже при использовании Flask.

Есть ли способ с помощью Flask или стороннего модуля, чтобы сделать это?

Дополнительная информация
Данные будут обновляться с использованием различных сокетов и последовательных портов.Каждый интерфейс будет работать в своем собственном потоке и обновлять общую память.Обратите внимание, что интерфейс Flask / web имеет доступ только для чтения в общую память, которая может обновляться другими потоками.

Общий пул клиентов никогда не должен превышать 20 человек.Это веб-интерфейс к тестовой системе, и в целом к ​​нему могут подключаться только 1-5 человек.

Ответы [ 4 ]

17 голосов
/ 12 декабря 2011

Чтобы не обновлять всю страницу, вы хотите использовать то, что называется 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
3 голосов
/ 12 декабря 2011

Я думаю, что, вероятно, самый простой способ сделать это - использовать javascript, как вы уже предлагали в своем вопросе.В этом случае Flask будет просто доставлять HTML-документ, который содержит некоторый код JavaScript, который должен быть выполнен браузером, поэтому я не понимаю, почему это может вызвать какие-либо проблемы для Flask.В этой странице я нашел несколько примеров использования различных комбинаций, таких как использование таймера (который, кажется, то, что вы ищете).

2 голосов
/ 12 декабря 2011

Нет.Ну, как минимум, в 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);
0 голосов
/ 29 декабря 2017

Один из способов добиться этого - использовать Flask через WebSockets, используя flask-socketio .Я использую 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...