在模型保存时在哪里调用 celery 任务

Gra*_*uff 0 python django celery

保存模型时我需要调用 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
Run Code Online (Sandbox Code Playgroud)

jau*_*e07 5

为了补充 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))

Run Code Online (Sandbox Code Playgroud)