2013-04-25 9 views
11

私はpython Flaskを使用してウェブサイトを構築しています。すべてがうまくいっていて、今ではセロリを実装しようとしています。Python Flask with Celery with application context

セロリからのフラスコメールを使って電子メールを送信しようとするまで、それはうまくいっていました。今、私は "アプリケーションコンテキストの外部での作業"エラーが発生しています。

完全なトレースバックが

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

どのソリューションが良いのかわかりません、セロリ全体のアプリケーションインスタンスまたはコールバック関数だけにコンテキストを追加します。 Flask Application Contextについては、http://flask.pocoo.org/docs/appcontext/ –

答えて

3

フラスコメールは仕事にフラスコのアプリケーションコンテキストを必要とします正しくセロリ側のアプリのオブジェクトをインスタンス化し、このようにapp.app_context使用:あなたのmail.pyファイルで

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

で読むことができます。どのようにしてフラスコのアプリケーションにセロリのアクセス権を与えることができますか?私は別々のファイルにそれらを持っています、それは間違っていますか? – Spuds

+0

Flaskの実行時と同じように、セロリファイルにアプリを読み込みます。あなたのFlaskアプリケーションに '__init __。py'を投稿しなければならないかもしれないし、もっと具体的にするために私の設定の詳細を追加しなければならないかもしれません。 –

+0

同じ問題がありますが、アプリケーションをインスタンス化し、そのようなコンテキスト内でセロリを開始することは機能しません。おそらく、タスクインスタンスがコンテキスト外で作成されたためですか? –

2

、あなたの「アプリ」と「メール」のオブジェクトをインポートします。次に、要求コンテキストを使用します。このような何か:

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

を私は任意のポイントを持っていないので、私はの答え上記codegeek @ upvoteことができませんでしたので、このような問題のための私の検索はこれで助けられたので、私は自分自身を書くことにしました質問/答え:私はちょうどパイソン/フラスコ/セロリのシナリオで同様の問題に取り組もうとしています。私のエラーがurl_forをセロリの仕事に使ってみようとしていたのに、あなたのエラーがmailを使用しようとしていたにもかかわらず、2つは同じ問題に関連していたと思います。 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