Flask-Mail разбивает сельдерей
У меня есть приложение Flask, в котором отлично работает сельдерей и Flask-Mail.
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()
ВСЕ ИДЕТ НОРМАЛЬНО
cel_test отлично работает с работником сельдерея; все проявляется в монго.
Но вот где это становится странным. Метод подписки плюс почта работает на 100% без @celery.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…)
ТРАССА
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'
Может кто-нибудь объяснить, почему в одном случае сельдерей работает отлично, но когда я использую mail.send (msg), он ломается?
Может быть, есть что-то, что мне нужно узнать с Python в целом?
Любые мысли, по крайней мере, как подход к этому типу вопроса будет принята с благодарностью.
1 ответ
Многое, что делается во флаке, связано с контекстом приложения. Например, render_template
функция, он должен знать, где ваше приложение хранит свои шаблоны. session
переменная хочет знать хранилище данных вашего приложения или систему кеширования. request
объект, и ваш mail.send
требовать некоторый контекст приложения при вызове.
Если вы хотите вызывать их вне области применения вашего фляги, как в вашей задаче celery, сделайте это в контексте приложения следующим образом:
...
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)
...
Обновить
Ошибка находится в части render_template send_email
задача.
@celery.task
def send_email(some_arg, name, email):
msg = Message(
subject='hello',
body=render_template('email.txt',
name=name,
some_arg=some_arg),
recipients=[email]
)
return mail.send(msg)
Когда я удаляю body=render_template
Каблаам, это работает.
у меня есть from flask import render_template
, возможно render_template
не может так работать?
Странно, без сельдерея send_email
плюс render_template
работает отлично.
Хакиш Успех
Когда я заставляю app_context
с другой функцией все работает:
def create_email(some_arg, name, email):
with app.test_request_context('/send_email'):
return render_template('email.txt',
name=name,
some_arg=some_arg)
а затем бросить его в send_email
задача так
body = render_template('email.txt'…
становится
body= create_email(some_arg, name)
И мы дома свободны.