How do I change the rendered template in Flask when a thread completes? How do I change the rendered template in Flask when a thread completes? flask flask

How do I change the rendered template in Flask when a thread completes?


An easy way is making cyclic Ajax requests to a thread_status endpoint that gives you information about the currently running task.

import timefrom flask import Flask, jsonifyfrom flask import render_templatefrom threading import Threadapp = Flask(__name__)th = Thread()finished = False@app.route("/")def init():    return render_template('index.html')@app.route("/", methods=['POST'])def load():    global th    global finished    finished = False    th = Thread(target=something, args=())    th.start()    return render_template('loading.html')def something():    """ The worker function """    global finished    time.sleep(5)    finished = True@app.route('/result')def result():    """ Just give back the result of your heavy work """    return 'Done'@app.route('/status')def thread_status():    """ Return the status of the worker thread """    return jsonify(dict(status=('finished' if finished else 'running')))if __name__ == "__main__":    app.run(debug=True)

So in your loading.html just insert a cyclic Ajax get() request:

<html>  <head>    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>    <script>      $(document).ready(function() {        var refresh_id = setInterval(function() {            $.get(              "{{ url_for('thread_status') }}",              function(data) {                console.log(data);                if (data.status == 'finished') {                  window.location.replace("{{ url_for('result') }}");                }              }            )}          , 1000);      });    </script>  </head>  <body>    <p>Loading...</p>  </body></html>

You can even append this by a progress counter if you like. But you need to take care that you prevent the thread from being run multiple times.