Update Django Model Field Based On Celery Task Status

天大地大妈咪最大 提交于 2019-12-23 17:06:45

问题


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:

  1. determine if the celery task was successful?
  2. 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!