我有一个烧瓶应用程序,可以调用任务。该任务从数据库中提取数据,绘制折线图并返回在html页面上呈现的html内容。没有Celery,Flask应用程序工作正常并在客户端呈现折线图,但现在我想委托celery通过RabbitMQ
代理运行任务,它运行它,因为我可以看到Celery shell中的日志输出,但结果html内容永远不会被发送回烧瓶服务器应用程序。怎么做?
#server-celery.py
app = Flask(__name__)
@app.route('/',methods=['GET'])
def index():
return render_template("index.html")
@app.route('/', methods=['GET', 'POST'])
def plotdata():
form = InputForm(request.form)
if request.method == 'POST' and form.validate():
lineChart = task.main.delay(form.startdate.data, form.enddate.data)
return render_template('view.html', form=form, result= lineChart)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True)
任务以Celery
worker运行:
#task.py
from celery import Celery
broker = 'amqp://localhost:5672'
app = Celery(__name__, broker=broker)
def queryDatabase(param1, param2):
#query database, return results
return data
def plotLineChart(data):
#plot data as line Chart
return LineChartHtmlcontent
@app.task
def main(param1,param2):
data = queryDatabase(param1,param2)
return plotLineChart(data)
和客户端html页面:
<!--view.html-->
<form method=post action="">
<table>
{% for field in form %}
<tr>
<td>{{ field.label }}</td>
<td>{{ field }}</td>
</tr>
{% endfor %}
</table>
<p><input type=submit value=Submit></form></p>
<p>
{% if result != None %}
<img src="{{ result }}" width="500">
{% endif %}
</p>
答案 0 :(得分:0)
更好的解决方案就是让使用celery异步运行任务,就像打算使用它一样,并在页面上使用javascript定期轮询芹菜任务以查看状态。
首先,在创建celery任务时,使用bind = True参数。这允许您将self
传递给函数。
@app.task(bind=True)
def main(self, param1, param2):
self.update_state(state='PENDING')
data = queryDatabase(param1,param2)
self.update_state(state='COMPLETE')
return plotLineChart(data)
您可以看到我们现在可以更新任务的状态。您可以修改代码以允许元数据加入update_state
方法,例如:self.update_state(state='PROGRESS', meta={'current': 0, 'total': 12})
现在你需要轮询芹菜任务,看看它是如何做的。
@blueprint.route('/status/<task_id>', methods=['GET'])
def taskstatus(task_id=None):
task = main.AsyncResult(task_id)
response = {
'state': task.state,
}
return jsonify(response)
当您使用任务ID轮询URL时,这将返回一个json对象。致电lineChart.id
.delay()
获取任务ID
请参阅miguel grinberg的优秀教程:http://blog.miguelgrinberg.com/post/using-celery-with-flask