使用 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)
在这里发帖是为了帮助像我这样的新手。
我通过 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)
在这里发帖是为了帮助像我这样的新手。