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

前端 未结 4 1573
夕颜
夕颜 2021-01-31 18:24

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 periodic

相关标签:
4条回答
  • 2021-01-31 18:41

    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
    
    0 讨论(0)
  • 2021-01-31 18:53

    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>
    
    0 讨论(0)
  • 2021-01-31 18:56

    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);
    
    0 讨论(0)
  • 2021-01-31 19:00

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

    0 讨论(0)
提交回复
热议问题