2013-04-25 4 views
11

Я создаю сайт, используя python Flask. Все идет хорошо, и теперь я пытаюсь внедрить сельдерей.Python Flask с сельдереем из контекста приложения

Это было хорошо, пока я не попытался отправить электронное письмо с использованием фляжки из сельдерея. Теперь я получаю ошибку «работа вне контекста приложения».

полные отслеживающий является

Traceback (most recent call last): 
    File "/usr/lib/python2.7/site-packages/celery/task/trace.py", line 228, in trace_task 
    R = retval = fun(*args, **kwargs) 
    File "/usr/lib/python2.7/site-packages/celery/task/trace.py", line 415, in __protected_call__ 
    return self.run(*args, **kwargs) 
    File "/home/ryan/www/CG-Website/src/util/mail.py", line 28, in send_forgot_email 
    msg = Message("Recover your Crusade Gaming Account") 
    File "/usr/lib/python2.7/site-packages/flask_mail.py", line 178, in __init__ 
    sender = current_app.config.get("DEFAULT_MAIL_SENDER") 
    File "/usr/lib/python2.7/site-packages/werkzeug/local.py", line 336, in __getattr__ 
    return getattr(self._get_current_object(), name) 
    File "/usr/lib/python2.7/site-packages/werkzeug/local.py", line 295, in _get_current_object 
    return self.__local() 
    File "/usr/lib/python2.7/site-packages/flask/globals.py", line 26, in _find_app 
    raise RuntimeError('working outside of application context') 
RuntimeError: working outside of application context 

Это моя почта функция:

@celery.task 
def send_forgot_email(email, ref): 
    global mail 
    msg = Message("Recover your Crusade Gaming Account") 
    msg.recipients = [email] 
    msg.sender = "Crusade Gaming [email protected]" 
    msg.html = \ 
     """ 
     Hello Person,<br/> 

     You have requested your password be reset. <a href="{0}" >Click here recover your account</a> or copy and paste this link in to your browser: {0} <br /> 

     If you did not request that your password be reset, please ignore this. 
     """.format(url_for('account.forgot', ref=ref, _external=True)) 
    mail.send(msg) 

Это мой сельдерей файл:

from __future__ import absolute_import 

from celery import Celery 

celery = Celery('src.tasks', 
       broker='amqp://', 
       include=['src.util.mail']) 


if __name__ == "__main__": 
    celery.start() 
+0

почты является flask_mail пример. при запуске приложения начинается инициирование почты из другого файла. – Spuds

+0

Я не знаю, какое решение было бы лучше, добавив контекст ко всему экземпляру приложения celery или только функцию обратного вызова. Но вы можете прочитать все о Контексте приложения фляги по адресу http://flask.pocoo.org/docs/appcontext/ –

ответ

3

Колба почте необходима контекст приложения фляги работать правильно. Создание объекта приложения на стороне сельдерея и использовать app.app_context так:

with app.app_context(): 
    celery.start() 
+0

Как я могу получить доступ к сельдерею к фляжному приложению? Я имею их в отдельных файлах прямо сейчас, это неправильно? – Spuds

+0

Импортируйте приложение в файл сельдерея, как вы делали бы при запуске Flask. Возможно, вам придется опубликовать свой '__init __. Py' для вашего приложения Flask или включить более подробную информацию о вашей настройке, чтобы я был более конкретным. –

+0

Имея ту же проблему, но создание экземпляра приложения и запуск сельдерея внутри контекста не работает. возможно, потому что экземпляр задачи был создан вне контекста? –

2

В файле mail.py, импортировать «приложение» и «почты» объекты. Затем используйте контекст запроса. Сделайте что-то вроде этого:

from whateverpackagename import app 
from whateverpackagename import mail 

@celery.task 
def send_forgot_email(email, ref): 
    with app.test_request_context(): 
     msg = Message("Recover your Crusade Gaming Account") 
     msg.recipients = [email] 
     msg.sender = "Crusade Gaming [email protected]" 
     msg.html = \ 
     """ 
     Hello Person,<br/> 
     You have requested your password be reset. <a href="{0}" >Click here recover your account</a> or copy and paste this link in to your browser: {0} <br /> 
     If you did not request that your password be reset, please ignore this. 
     """.format(url_for('account.forgot', ref=ref, _external=True)) 

     mail.send(msg) 
+1

Я думаю, что использование test_request_context в не-тестовой среде - не очень хорошая идея. – jaapz

+0

Это решило проблему при использовании Flask-Babel в сочетании с сельдереем. Flask-Babel не загружает никаких переводов без запроса (потому что он кэширует переводы в контексте запроса).Кроме того, Flask-Babel умеет отлично работать без запроса. Поэтому использование 'test_request_context()' - это просто простой способ построения функционального контекста, хотя он может быть немного расточительным. –

2

У меня нет ни одного очка, так что я не мог upvote @ codegeek х выше ответ, поэтому я решил написать свою собственную, так как мой поиск такой проблемой, как это помогло этим вопрос/ответ: у меня был некоторый успех, пытающийся решить подобную проблему в сценарии python/flask/celery. Несмотря на то, что ваша ошибка заключалась в попытке использовать , в то время как моя ошибка заключалась в попытке использовать url_for в задаче на сельдерей, я подозреваю, что эти два были связаны с одной и той же проблемой, и что у вас были бы ошибки, связанные с использованием url_for, если бы у вас были попытался использовать это до mail.

Без контекста приложения, присутствующего в задаче сельдерея (даже после включения import app from my_app_module), я тоже получал ошибки. Вы должны будете выполнить mail операции в контексте приложения:

from module_containing_my_app_and_mail import app, mail # Flask app, Flask mail 
from flask.ext.mail import Message # Message class 

@celery.task 
def send_forgot_email(email, ref): 
    with app.app_context(): # This is the important bit! 
     msg = Message("Recover your Crusade Gaming Account") 
     msg.recipients = [email] 
     msg.sender = "Crusade Gaming [email protected]" 
     msg.html = \ 
     """ 
     Hello Person,<br/> 
     You have requested your password be reset. <a href="{0}" >Click here recover your account</a> or copy and paste this link in to your browser: {0} <br /> 
     If you did not request that your password be reset, please ignore this. 
     """.format(url_for('account.forgot', ref=ref, _external=True)) 

     mail.send(msg) 

Если кому-то интересно, мое решение проблемы использования url_for в задачах сельдерея можно найти here

Смежные вопросы