简体   繁体   中英

Flask + jQuery: Render different template once thread finishes

I'm kind of new to Flask and I need some help. I creating a Flask where the user uploads a file, which will then be processed. The process takes about 1 to 2 minutes, but during this processing time, I want to render a “loading” HTML, which will be replaced by the Results.html ones the process is done. I thought I could make this work with jQuery (My JS knowledge is very limited). I referenced this question but for some reason, it doesn't work. If someone could possibly help me, it would be appreciated.

python (simplyfied):

th = Thread()
finished = False


@app.route("/<jobid>/", methods=["GET"])
def upload_complete(jobid):

    #code I can’t show 

    global th 
    global finished
    finished = False
        
    th = threading.Thread(target=test_thread, args=[6])
    th.start()
    return render_template("loading.html", jobid=jobid)
            
def test_thread(sec):
    global finished 
    print ("starting")
    time.sleep(sec)
    print ("finished")
    finished = True 

@app.route('/result')
def result():
    return 'Done'


@app.route('/status')
def thread_status():
    return jsonify(dict(status=('finished' if finished else 'running')))

loading.html:

{% extends "templates/base.html" %}
{% block script %}
<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>
{% endblock %}
{% block title %}
succesfull upload
{% endblock %}
{% block main %}
<h1>loading</h1>
{% endblock %}

The threads works fine and the loading HTML is rendered only the result page isn't displayed once the thread is done. I don't know where or not this is important but the results in my terminal is the following:

127.0.0.1 - - [16/Dec/2020 14:53:08] "POST /upload/ HTTP/1.1" 302 -
starting
127.0.0.1 - - [16/Dec/2020 14:53:08] "GET /55953bfc-0795-4b4d-8d7b-a38afd2edbd5/ HTTP/1.1" 200 -
127.0.0.1 - - [16/Dec/2020 14:53:08] "GET /favicon.ico/ HTTP/1.1" 200 -
finished

When you create a new thread, you're working with different processes and the communication between them is always kind of tricky.

You may use the method .is_alive() which returns True if your thread is still running.

@app.route('/status')
def thread_status():
    global th

    return jsonify(dict(status=('running' if th.is_alive() else 'finished')))

If is_alive() is still returning True even when your computation is finished, you might add sys.exit(0) (and, of course, import sys statement) at the end of your Thread script to make sure the process will terminate after everything is done.

However, requesting information from your server multiple times is not performative and you can easily take down your server if multiple clients require some real-time information. If you need to provide real-time information to your users, you should take a look into WebSockets. This answer might help with it.

I'm working with bootstrap and had the slim version of jQuery imported... AJAX loses its functionality this way:

fix in my base template after <main></main> :

<!-- jQuery, Popper.js, and Bootstrap JS -->
<!--script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script-->
<!--bootstraps jQuery version causes issues with AJAX functionality so import another version of jQuery-->
<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.min.js" integrity="sha384-w1Q4orYjBQndcko6MimVbzY0tgp4pWB4lZ7lr30WKz0vr/aWKhXdBNmNb5D92v7s" crossorigin="anonymous"></script>
    

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM