2016-12-25 49 views
1

我有一個功能,抓取網絡的數據和計算搜索的分數。但是,這可能需要一段時間,有時在完成執行之前網頁會超時。線程完成後,如何更改Flask中呈現的模板?

所以我創建了一個獨立的線程來執行函數,loading.html告訴客戶端數據仍在被收集。一旦該功能在線程中結束,如何重新加載網頁以顯示output.html,以顯示分數。

這是我至今一個簡單的版本:

from flask import Flask 
from flask import render_template 
from threading import Thread 

app = Flask(__name__) 

@app.route("/") 
def init(): 
    return render_template('index.html') 

@app.route("/", methods=['POST']) 
def load(): 
    th = Thread(target=something, args=()) 
    th.start() 
    return render_template('loading.html') 

def something(): 
    #do some calculation and return the needed value 

if __name__ == "__main__": 
    app.run() 

我怎麼路線我的應用程序render_template('output.html', x=score)一次something()線程裏面th結束?

我想避免像redis這樣的任務隊列,因爲我想部署這個應用程序在網絡上,我不想招致費用(這是一個實驗和業餘愛好)。

與代碼了詳細的解答將有很大的幫助,因爲我是新來的燒瓶中,多線程

回答

1

一個簡單的方法是使循環Ajax請求到thread_status端點爲您提供有關當前正在運行的任務信息。

import time 
from flask import Flask, jsonify 
from flask import render_template 
from threading import Thread 

app = 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) 

所以在你loading.html只需插入循環阿賈克斯get()要求:

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

您可以通過進度計數器,如果你喜歡,甚至追加此。但是你需要小心,防止線程多次運行。

+0

這工作就像我想要的一樣!謝謝!不知道爲什麼我沒有考慮過編寫javascript函數 – Apara