使用 Backgroundscheduler 定期更新烧瓶中的值

periodically updating a value in flask with Backgroundscheduler

我通过 windows 在 Flask 中工作,我也在使用 BackgroundScheduler。我打算做的是通过单击一个按钮启动 backgroundscheduler,之后,我希望看到一个值根据我指定的时间间隔增加。我目前遇到的问题是我需要多次按下开始按钮才能看到更新后的值。

我有以下代码:

我的简化版 Flask 应用程序:

from flask import Flask, Response, render_template
from flask_wtf import FlaskForm
from flask_bootstrap import Bootstrap
from apscheduler.schedulers.background import BackgroundScheduler

app = Flask(__name__)
# Starting my value in 0
some_value = 0

# This function only increases the variable by 1
def interval_task():
    global some_value
    some_value += 1
    
bootstrap = Bootstrap(app)

# A simplified route with two buttons
@app.route('/page1', methods = ['GET','POST'])
def click_buttons():
    
    img_pause = '/static/img/bootstrap_icons/pause-circle.svg'
    img_working = '/static/img/animated_captura.gif'
    sched = BackgroundScheduler(daemon = True)
    sched.add_job(func = interval_task, trigger = 'interval', id = 'fetch_data_cont', seconds = 5)
    
    if request.form.get('startbtn') == 'startbtn':
    
        sched.start()
        
        # This is were I have problems. If I return the render_template, flask updates the form, but only
        # briefly, I need to keep on pressing the start button to see the updated value.

        return render_template('page1.html', img_source = img_working, some_value = some_value)
        
    if request.form.get('stopbtn') == 'stopbtn':
        
        sched.pause_job('fetch_data_cont')
        return render_template('page1.html', img_source = img_pause)  
    
    else:
        
        sched.pause_job('fetch_data_cont')
        return render_template('page1.html', img_source = img_pause)  

if __name__ == '__main__':
    import webbrowser
    webbrowser.open("http://127.0.0.1:5000/")
    #app.run(debug = True)
    app.run()

在我的 html:

<!DOCTYPE html>
    
{% extends "base.html" %}

{% block leftsidebar %}
        
    <form  method="POST">
        <div class="bs-component">
            <div class="card border-dark mb-3" style="max-width: 20rem;">
                <div class="card-header">some fancy title here</div>
                <div class="card-body">
                    <input type="submit" class="btn btn-primary" name="startbtn" value="startbtn">
                    <img src="{{ img_source }}" style="width:80px;height:40px;" onerror="this.style.display='none'">
                    <hr>
                    <input type="submit" class="btn btn-primary" name="stopbtn" value="stopbtn">
                </div>
            </div>  
        </div>
        
        <div class="bs-component">
            <div class="card border-dark mb-3" style="max-width: 20rem;">
                <div class="card-header">Output</div>
                <div class="card-body">
                    
                    <p class="card-text">
                        rms: {{ some_value }}
                    </p>
                        
                </div>
            </div>
        </div>  
        
        
    </form>

{% endblock %}


{% block center %}

    <h2>some other fancy title for the page1</h2>
    <p><i>Some nice info.</i></p>
    <div class="bs-component">
        <div style = "background-image: href="{{ url_for('static', filename='equipo_1.png') }}";"></div>
    </div>

{% endblock %}

我知道烧瓶是这样工作的;你按下一个按钮,它会在 html 中呈现一些新的东西,但是我如何通过只按下我的按钮一次来获得多个变化的输出?

也许我的问题有一个简单的解决方案,但到目前为止(对 Flask 来说仍然是个新手)我还没有找到它。如有任何帮助,我们将不胜感激。


编辑: 在@sur.la.route的建议下我做了一些修改:

{% block leftsidebar %}
    <form  method="POST">       
       <div class="bs-component">           
          <div class="card border-dark mb-3" style="max-width: 20rem;">
              <div class="card-header">Captura continua</div>
                  <div class="card-body">
                      <input type="submit" id="btncapt" class="btn btn-primary" name="comenzar" value="comenzar">
                      <img src="{{ img_source }}" style="width:80px;height:40px;" onerror="this.style.display='none'">
                      <hr>
                      <input type="submit" class="btn btn-primary" name="detener" value="detener">
              </div>            
           </div>           
        </div>
     </form>        

         <div class="bs-component">         
             <div class="card border-dark mb-3" style="max-width: 20rem;">           <div class="card-header">Respuesta</div>           <div class="card-body">
                
                <p class="card-text" id="updtval">
                    
                </p>
                </div>      
            </div>
        </div>  
<script>    
document.getElementById("btncapt").onclick = myTimer;       
function myTimer(some_value){   
    var req = new XMLHttpRequest();         
    req.open("GET", "/intervaltask", true);          
    document.getElementById("updtval").innerHTML = "rms = " + req.responseText;         
    req.send();     
}   
setInterval(myTimer, 5000);     
</script>
{% endblock %}

虽然我的 Flask 应用程序中的更改很小:

some_value = 0

@app.route('/intervaltask')
def interval_task():
    global some_value
    some_value += 1
    # This is just to check the value on the console, it is increasing
    print (some_value)
    return str(some_value)

因此,我可以看到值在增加并且确实出现了 rms= 的文本,但没有其他内容。我做了一点video的问题...

这是我推荐的示例。我会使用按钮将其打开,然后使用 javascript ajax 请求定期查询更新值。

我敢肯定有一些错别字,但你会明白的:)

添加一个 flask 路由,它将 return 值仅 -

@app.route('/ajax')
def ajax():
    return some_value

然后,在你的 page1.html 的末尾添加一个 javascript 函数,我想你的 block center.

<script>
(function(){

  function get_value(){
    // create an ajax request
    var q = new XMLHttpRequest();
  
    q.open("get", "/ajax", true);
    q.send();
  
    q.onload = function () {
      // update page with new value
      document.queryselector('div.bs-component p.card-text').innerHTML = "rms: " + q.responseText;

      // timeout to run again after 2 seconds
      setTimeout(get_value, 2000);
    }
  }
  
  // call the function to get it started
  get_value();

})();
</script>

所以...有两件事要解决:javascript 正在重置自己,只是因为 type="submit" 指令,根据另一个问题及其各自的答案,已发布

如果我摆脱它,程序运行良好,另一件事是 AJAX 请求的顺序。有很多站点 send() 它位于起始代码的开头,但它不应该在那里。把它放在最后。我还添加了一些其他内容,例如您期望的 return 类型,并且在烧瓶中,我正在 returning 一个字符串。

所以...在 html 文件中,对我有用的脚本是:

<script>
    document.getElementById("btncapt").addEventListener("click", startTimer);

    function startTimer(){
        var setime = setInterval(myTimer, 5000);
    }

    function myTimer(){
        var req = new XMLHttpRequest();
        req.onload = function(){
            document.getElementById("updtval").innerHTML = "rms = " + req.responseText;
        }
        req.open("GET", "/intervaltask", true);
        req.responseType = "text";
        req.send();
    }
</script>

你的 Flask 应用程序中的代码可以是:

some_value = 0

@app.route('/intervaltask') def interval_task():
    global some_value
    some_value += 1
    print (some_value)
    return str(some_value)

在这里发帖是为了帮助像我这样的新手。