问题
In my model, I have a status
field with a default value of 'Processing'. In the Django admin interface, after user clicks 'Save' button, the form inputs are passed to a celery task that just sleeps for 30 seconds.
After that 30 seconds, how do I:
- determine if the celery task was successful?
- update the model's
status
field from 'Processing' to the actual status (ex: Completed, Failed?
models.py
from django.db import models
class Scorecard(models.Model):
name = models.CharField(max_length=100, unique=True)
status = models.CharField(max_length=20, default='Processing')
def __str__(self):
return self.name
admin.py
from django.contrib import admin
from scorecards.models import Scorecard
from scorecards.tasks import get_report
class ScorecardAdmin(admin.ModelAdmin):
list_display = ['name', 'status']
def save_model(self, request, obj, form, change):
if form.is_valid():
data = form.cleaned_data
name = data['name']
get_report.delay(name)
super().save_model(request, obj, form, change)
admin.site.register(Scorecard, ScorecardAdmin)
tasks.py
from __future__ import absolute_import, unicode_literals
from celery import shared_task
from time import sleep
@shared_task
def get_report(name):
sleep(30)
Real-time status of the celery task updating the status
field every x time intervals would be nice, but for now I'm just really curious how to do this at all.
回答1:
I didn't figure out real-time status (yet) but did manage to change the status once a task is completed.
These were the main parts below. The critical reason to understand why this works is that I'm starting a celery worker in --pool=solo
like so:
celery -A scorecard worker --pool=solo -l info
This is a single-threaded execution pool (which is fine for my current purposes) but it means it will process the first task get_report(name)
, and when that's done, process the set_task_status(id)
where it checks the status of the result and sets the status field to be whatever the actual status is.
models.py
class Scorecard(models.Model):
....
task_id = models.CharField(max_length=50)
admin.py
class ScorecardAdmin(admin.ModelAdmin):
...
result = get_report.delay(name)
set_task_status.delay(result.task_id)
...
tasks.py
@shared_task
def get_report(name):
sleep(30)
@shared_task
def set_task_status(id):
instance = Scorecard.objects.get(task_id=id)
task_status = AsyncResult(id)
instance.status = task_status.status
instance.save()
This is what I've figured out so far.
来源:https://stackoverflow.com/questions/47737175/update-django-model-field-based-on-celery-task-status