在模型保存中在何处调用芹菜任务

时间:2018-12-23 05:37:50

标签: python django celery

保存模型时,我需要调用芹菜任务。我有冲突的导入,我不知道如何解决。我想知道是否有人知道我可以构造这种方式以避免进口冲突

models.py
from .tasks import celery_task

class Picture(PolymorphicModel):
    file = models.ImageField()
    processed_file = models.ImageField(blank=True, null=True)
    ...
    def save(self, *args, **kwargs):
        if self.file:
            self.processed_file = celery_task.delay(self.id, other_arg)
        super(Picture, self).save(*args, **kwargs)




tasks.py
from .models import Picture

@task
def celery_task(id, other_arg):
    try:
        picture = Picture.objects.get(id=id)
    except ObjectDoesNotExist:
        picture = None

    if picture:
        return some_other_function(picture.file)

    return None

2 个答案:

答案 0 :(得分:2)

请注意,您调用任务并期望其工作的方式存在问题,但这在您的问题范围之外。要修复循环导入,只需使用本地导入而不是全局导入即可:


models.py

class Picture(PolymorphicModel): file = models.ImageField() processed_file = models.ImageField(blank=True, null=True) ... def save(self, *args, **kwargs): from .tasks import celery_task if self.file: self.processed_file = celery_task.delay(self.id, other_arg) super(Picture, self).save(*args, **kwargs)
tasks.py
from .models import Picture @task def celery_task(id, other_arg): try: picture = Picture.objects.get(id=id) except ObjectDoesNotExist: picture = None if picture: return some_other_function(picture.file) return None

答案 1 :(得分:1)

要补充2ps的答案,使用此代码结构将遇到数据库争用条件。我发现本文对解决他们https://www.vinta.com.br/blog/2016/database-concurrency-in-django-the-right-way/

特别有用
  

当两个或多个并发线程尝试同时访问同一内存地址(或在这种情况下,是数据库中的某些特定数据)时,就会发生数据竞争情况。

这意味着Django应用程序和Celery应用程序线程尝试同时访问Picture实例。本文指出了三种解决方法,但是对我有用的一种方法是使用transaction.on_commit(lambda: your_celery_task.delay())

在您的情况下,应该是:

models.py
from .tasks import celery_task
from django.db import transaction

class Picture(PolymorphicModel):
    file = models.ImageField()
    processed_file = models.ImageField(blank=True, null=True)
    ...
    def save(self, *args, **kwargs):
        super(Picture, self).save(*args, **kwargs)
        if self.file:
            transaction.on_commit(lambda: celery_task.delay(self.id))