Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flask-Mail breaks Celery

I've got a Flask app where celery works fine and Flask-Mail on its own works fine as well.

from celery import Celery
from flask_mail import Mail, Message
app = Flask(__name__)
mail = Mail(app)

celery = Celery('main_app', 
                 broker='mongodb://localhost',
                 backend='mongodb://localhost')
@celery.task
def cel_test():
     return 'cel_test'

@app.route('/works_maybe')
def works_maybe():
    return cel_test.delay()

SO FAR, SO GOOD

cel_test works fine with the celery worker; everything shows up in mongo.

But here's where it gets weird. The "signup" plus mail method works 100% without @celery.task, but blows up when it becomes a task.

@celery.task
def send_email(some_arg, name, email):
    msg = Message(…message details..)
    return mail.send(msg)

@app.route("/signup", methods=['POST'])
def signup():
    return send_email.delay(...stuff for the message…)

THE TRACE

R = retval = fun(*args, **kwargs)
File "/Users/username/pymods/virtualenvs/directory/lib/python2.7/site-packages/celery-3.0.15-py2.7.egg/celery/task/trace.py", line 415, in __protected_call__
return self.run(*args, **kwargs)
File "/Users/username/pymods/directory/directory/main_app/main_app.py", line 43, in send_email
something = 'a string in the Message'),
File "/Users/username/pymods/virtualenvs/directory/lib/python2.7/site-packages/flask/templating.py", line 123, in render_template
ctx.app.update_template_context(context)  
AttributeError: 'NoneType' object has no attribute 'app'

Could someone explain why in one case celery works great but when I involve mail.send(msg) it breaks?

Perhaps there is something I need to learn with python more generally?

Any thoughts, if at least as to approach to this type of issue would be greatly appreciated.

like image 359
Stuart Avatar asked Feb 23 '26 01:02

Stuart


1 Answers

A lot of things done in flask are bound to the application context. For example, the render_template function, it needs to know where your application stores its templates. The session variable wants to know your application's data store or caching system. The request object, and your mail.send require some application context when being called.

If you want to call them outside the scope of your flask application, like in your celery task, do it within the app context like so:

...

with app.app_context():

    do_some_context_bound_actions()

    msg = Messgae(...)
    user_name = app.session["user"].name
    msg.html = render_template("mail/welcome.html", name=user_name)
    mail.send(msg)

...
like image 66
aduuna Avatar answered Feb 24 '26 14:02

aduuna



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!