Reputation: 1519
I've got a simple Python Flask/Celery app that's running into issues with flashing messages after a delay. I'm using Celery's delay() function to call a function that sleeps for 5 seconds, then flashes a message. Despite using with app.app_context()
in my background function, Celery reports:
RuntimeError: Working outside of request context
I've also tried the @copy_current_request_context
decorator, as mentioned by this question, but then I get
RuntimeError: This decorator can only be used at local scopes when a request context is on the stack. For instance within view functions
app.py:
from flask import Flask, flash, render_template, request
from celery import Celery
import time
app = Flask(__name__)
app.config['CELERY_BROKER_URL'] = 'redis://localhost:6379/0'
app.config['CELERY_RESULT_BACKEND'] = 'redis://localhost:6379/0'
celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
celery.conf.update(app.config)
@celery.task
def my_background_task():
with app.app_context():
time.sleep(5)
flash("Background task complete.")
@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "POST":
task = my_background_task.delay()
return render_template("index.html")
else:
return render_template("index.html")
if __name__ == "__main__":
app.run(debug=True,host='0.0.0.0')
templates/index.html:
<!doctype html>
{% with messages = get_flashed_messages() %}
{% if messages %}
<ul class=flashes>
{% for message in messages %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
{% endwith %}
{% block body %}
<form method="POST">
<input type="submit" name="submit" value="Submit request">
</form>
{% endblock %}
I'm running the app with three terminal windows: running Redis with redis-server
, running Celery with celery worker -A app.celery --loglevel=info
, and running Python with python app.py
.
Upvotes: 3
Views: 2871
Reputation: 2887
The problem is that celery tasks are run by celery, they're not part of a request done by a browser or any other client so they will always be unbound since they don't know to what client they're supposed to be replying.
Running background tasks isn't really meant to interact with clients but to trigger other work (such as sending emails), unless we're using websockets or server-sent events.
Upvotes: 2