2013-04-25 4 views
11

Ich baue eine Website mit Python Flask. Alles läuft gut und jetzt versuche ich Sellerie zu implementieren.Python Flask mit Sellerie außerhalb der Anwendung Kontext

Das lief auch gut, bis ich versuchte, eine E-Mail mit Flaschenpost aus Sellerie zu senden. Jetzt bekomme ich einen Fehler "außerhalb des Anwendungskontexts arbeiten".

vollständige Rückverfolgung ist

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 

Diese meine Mail-Funktion ist:

@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) 

Das ist mein Sellerie-Datei:

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

Mail ist der flask_mail finden Beispiel. Mail wird beim Starten der App aus einer anderen Datei initiiert. – Spuds

+0

Ich weiß nicht, welche Lösung besser wäre, indem ich den Kontext der gesamten Sellerie-Anwendungsinstanz oder nur der Callback-Funktion hinzufüge. Aber Sie können alles über den Flask Application Context lesen unter http://flask.pooco.org/docs/appcontext/ –

Antwort

3

Flask-Mail muss die Flasche Anwendungskontext arbeiten korrekt. Instanziieren die App Objekt auf der Sellerie Seite und verwenden app.app_context wie folgt aus:

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

Wie gebe ich Sellerie Zugriff auf die Flasche App? Ich habe sie jetzt in getrennten Dateien, ist das falsch? – Spuds

+0

Importieren Sie die App in die Sellerie-Datei, als würden Sie Flask ausführen. Sie müssen möglicherweise Ihr '__init __. Py' für Ihre Flask-App posten oder weitere Details Ihrer Einrichtung hinzufügen, um genauer zu sein. –

+0

Das gleiche Problem zu haben, aber die App instanziieren und den Sellerie im Kontext starten, funktioniert nicht. Vielleicht, weil die Aufgabeninstanz außerhalb des Kontexts erstellt wurde? –

2

In Ihrer mail.py Datei importieren Sie Ihre „app“ und „Mail“ Objekte. Verwenden Sie dann den Anforderungskontext. Tun Sie etwas wie folgt aus:

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

Ich denke, test_request_context in einer Nicht-Testumgebung ist keine gute Idee. – jaapz

+0

Dies löste ein Problem bei der Verwendung von Flask-Babel in Kombination mit Sellerie. Flask-Babel lädt keine Übersetzungen ohne eine Anfrage (weil die Übersetzungen im Anfragekontext zwischengespeichert werden).Abgesehen davon ist Flask-Babel in der Lage, ohne die Anfrage gut zu funktionieren. Die Verwendung von 'test_request_context()' ist also nur eine einfache Möglichkeit, einen funktionalen Kontext zu erstellen, auch wenn es möglicherweise etwas verschwenderisch ist. –

2

Ich habe keine Punkte haben, so konnte ich nicht upvote @ codegeek die oben genannte Antwort, so habe ich beschlossen, meine eigene zu schreiben, da meine Suche nach einem Thema wie diesem durch das half wurde Frage/Antwort: Ich hatte gerade Erfolg damit, ein ähnliches Problem in einem Python/Flaschen/Sellerie-Szenario zu lösen. Obwohl Ihr Fehler von mailmail versucht wurde, während mein Fehler um url_for in einer Sellerie-Aufgabe zu verwenden war, vermute ich, dass die beiden mit dem gleichen Problem verbunden waren und dass Sie Fehler gehabt hätten, die von der Verwendung von url_for stammten, wenn Sie hatten versuchte, das vor mail zu verwenden.

Ohne Kontext der App in einer Sellerie-Aufgabe (auch nach dem Einschluss einer import app from my_app_module) Ich bekam auch Fehler. Sie müssen den mail Betrieb im Rahmen der App auszuführen:

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) 

Wenn jemand interessiert ist, meine Lösung für das Problem der url_for in Sellerie Aufgaben verwenden, kann here

Verwandte Themen