What is the best way to implement a forced page refresh using Flask?

Question:

Background
I have a large number of fields that will be updating real time from an external process. I would like to update the Flask hosted pages periodically to show connected users any changes. Ideally the whole page would not refresh, this was a complaint of a similar system, but rather just update a number of fields on the page.

Current Direction
My current thoughts is to use possibly use a JavaScript to handle this, but I’m not sure if that’s even possible when using Flask.

Is there a way with Flask, or 3rd party module, to accomplish this?

Additional Information
The data will be updated using various sockets and serial ports. Each interface will be running in its own thread and updating shared memory. Note that the Flask / web interface has read-only writes to shared memory that can be updated by the other threads.

The total client pool should never exceed 20 people. This is a web interface to a test system and in general will only have 1-5 people connected to it at any given time.

Asked By: Adam Lewis

||

Answers:

I think probably the easiest way to do this is using javascript as you already suggest in your question. In this case, Flask would be just delivering an HTML document that contains some javascript code to be executed by the browser, so I don’t see why this could cause any problem to Flask. In this page, I’ve found some examples using different combinations such as using a timer (which seems to be what you’re looking for).

Answered By: jcollado

No. Well, as least there’s nothing in side of Flask that would make this easier than other solutions. SO has some decent material on implementing comet servers in Python.

As you mentioned, there you can use JavaScript to poll the server for new data. This can be difficult for your server to manage though if you have many users. Opening concurrent TCP connections is fairly expensive. It also means that your UI may appear slightly jerky, because things will be updating every second or so, rather than when new data hits the server.

With that in mind, Flask is excellent for this second choice because it is so easy to attach response functions to individual URLs. The main thing to note is you should functions which block heavily on I/O. Long-running functions will seize the whole application.

Let’s say you have two temperature gauges & you’re using 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)

In a JavaScript file, you could have some function that updates a DOM element every minute with the current temperature. This code should give you some idea of something you can build into an actual implementation:

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);
Answered By: Tim McNamara

To avoid refreshing the entire page you want to use what is called AJAX. It looks like this is easy to implement in flask.

Since you want it to happen periodically you need to call your AJAX functions from a timer function in javascript.

This means you just put the javascript from the flask page inside a timer call.

Here’s approximately what the javascript would look like:

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
Answered By: Michael Anderson

One way to achieve this is in Flask through WebSockets using flask-socketio. I use APScheduler for the background process in the example, but any background process will do. this updates a price on the webpage every 4 seconds:

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')

Then the index.html template is:

<!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>
Answered By: Vladtn
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.