2016-07-08 6 views
0

Wie man celery Worker return Task Ergebnisse zu Kolben machen? Ich habe eine Kolben-App, die eine Aufgabe aufruft. Die Aufgabe zieht Daten aus der Datenbank, stellt Liniendiagramme dar und gibt HTML-Inhalte zurück, die auf einer HTML-Seite gerendert werden. Ohne Sellerie funktioniert die Flask-App gut und rendert Liniendiagramm auf Client-Seite, aber jetzt möchte ich Sellerie Aufgabe über RabbitMQ Broker delegieren, die es ausgeführt wird, wie ich die Log-Ausgaben in Sellery-Shell sehen kann, aber die resultierende HTML-Inhalt wird nie zurück zur Flashin Server App gesendet. Wie geht das?How to make Sellerie Worker return Ergebnisse von Aufgabe

#server-celery.py 

app = Flask(__name__) 

@app.route('/',methods=['GET']) 
def index(): 
    return render_template("index.html") 

@app.route('/', methods=['GET', 'POST']) 
def plotdata(): 
    form = InputForm(request.form) 
    if request.method == 'POST' and form.validate(): 
     lineChart = task.main.delay(form.startdate.data, form.enddate.data) 
     return render_template('view.html', form=form, result= lineChart) 

if __name__ == '__main__': 
    app.run(host='0.0.0.0', port=5000, debug=True) 

Und die Aufgabe als Celery Arbeiter ausgeführt wird:

#task.py 
from celery import Celery 

broker = 'amqp://localhost:5672' 
app = Celery(__name__, broker=broker) 

def queryDatabase(param1, param2): 
    #query database, return results 
    return data 

def plotLineChart(data): 
    #plot data as line Chart 
    return LineChartHtmlcontent 

@app.task 
def main(param1,param2): 
    data = queryDatabase(param1,param2) 
    return plotLineChart(data) 

und Client-HTML-Seite:

<!--view.html--> 

<form method=post action=""> 
<table> 
    {% for field in form %} 
    <tr> 
    <td>{{ field.label }}</td> 
     <td>{{ field }}</td> 

    </tr> 
    {% endfor %} 
</table> 
<p><input type=submit value=Submit></form></p> 

<p> 
{% if result != None %} 
<img src="{{ result }}" width="500"> 
{% endif %} 
</p> 
+0

Wenn Sie das Ergebnis sofort benötigen, warum Sie Sellerie verwenden? Das ist für die Ausführung lang andauernder Aufgaben im Hintergrund. – davidism

+0

Sie können diese Methode verwenden http://docs.selleryproject.org/en/latest/reference/sellery.result.html#sellery.result.AsyncResult.get Aber was ist der Sinn der Verwendung von Sellerie in diesem Fall? Es blockiert die Ausführung, bis das Ergebnis zurückgegeben wird. Und der Hauptgrund, Sellerie zu verwenden, ist, Aufgabe im Hintergrund auszuführen. Es ist besser, Ihre Ergebnisse irgendwo zu speichern. –

+0

@davidism ist ein Follow-up von http://stackoverflow.com/questions/37839551/how-to-restart-flask-process-by-refreshing-page/38146003#38146003 – ArchieTiger

Antwort

0

Eine bessere Lösung einfach ist die Aufgabe laufen asynchron mit Sellerie zu lassen, wie es war beabsichtigt, verwendet zu werden und verwenden Sie Javascript auf der Seite, um die Sellerieaufgabe regelmäßig abzufragen, um den Status zu sehen.

Zuerst, wenn Sie Ihre Sellerie Aufgabe erstellen verwenden Sie den Bind = True Parameter. Damit können Sie self in die Funktion übernehmen.

@app.task(bind=True) 
def main(self, param1, param2): 
    self.update_state(state='PENDING') 
    data = queryDatabase(param1,param2) 
    self.update_state(state='COMPLETE') 
    return plotLineChart(data) 

Sie können sehen, dass wir jetzt den Status der Aufgabe aktualisieren können. Sie können den Code ändern Metadaten in die update_state Methode zu ermöglichen, als auch, zum Beispiel: self.update_state(state='PROGRESS', meta={'current': 0, 'total': 12})

Jetzt müssen Sie die Sellerie Aufgabe abzufragen, um zu sehen, wie es zu tun.

Dadurch wird ein JSON-Objekt zurückgegeben, wenn Sie die URL mit der Aufgaben-ID abfragen. Sie können die Task-ID erhalten, indem lineChart.id, nachdem Sie rufen .delay()

Bitte beachten Sie die hervorragende Anleitung von miguel grinberg: http://blog.miguelgrinberg.com/post/using-celery-with-flask