Django - 从模型中通过芹菜执行任务

时间:2011-11-12 19:48:14

标签: django rabbitmq celery

在我的models.py中:

from django.db import models
from core import tasks

class Image(models.Model):
    image     = models.ImageField(upload_to='images/orig')
    thumbnail = models.ImageField(upload_to='images/thumbnails', editable=False)

    def save(self, *args, **kwargs):
       super(Image, self).save(*args, **kwargs)
       tasks.create_thumbnail.delay(self.id)

在我的tasks.py中:

from celery.decorators import task
from core.models import Image

@task()
def create_thumbnail(image_id):
    ImageObj = Image.objects.get(id=image_id)
    # other stuff here

这将返回以下内容:

  • 异常类型: ImportError
  • 例外值:无法导入名称任务

如果我在from core.models import Image中注释tasks.py,则错误消失,但这显然会导致问题,因为Image在此处没有任何意义。我尝试在create_thumbnail内导入它,但它仍然无法识别Image

我已经读过某个地方,通常对象本身可以作为参数传递给任务,这将解决我的问题。但是,一位朋友曾告诉我,在RabbitMQ消息中尽可能少地发送数据被认为是最佳做法,所以要实现这一点,我只想传递图像ID,然后在任务中再次检索它。

1)我正在尝试做的是最佳做法吗?如果是,我该如何解决?

2)我注意到在网络上发现的所有例子中,他们都是从视图中执行任务,而不是从模型中执行。我正在尝试在上传新图像时创建缩略图,我不想在我拥有的每个表单/视图中调用create_thumbnail。有什么想法吗?是从不推荐的模型执行任务还是常规做法?

3 个答案:

答案 0 :(得分:14)

  

1)我正在尝试做的是最佳做法吗?如果是,我该如何解决?

是的,只传递一点信息到这个任务通常是你提到的好事。

  

2)我注意到在网络上发现的所有例子中,他们都是从视图中执行任务,而不是从模型中执行。我正在尝试在上传新图像时创建缩略图,我不想在我拥有的每个表单/视图中调用create_thumbnail。有什么想法吗?是从不推荐的模型执行任务还是常规做法?

我注意到了同样的事情,觉得教程和文档从他们的视图中调用任务,因为使用简单的视图比使用模型或表单更容易演示事物是如何工作的。

要消除循环导入,您应该考虑导入应该采用哪种方式。通常,tasks.py需要从models.py导入很多东西,而models.py很少需要了解tasks.py。标准应该是models.py不从tasks.py导入。因此,如果您确实需要执行此操作并从模型方法调用任务,请在方法中进行导入:

from django.db import models

class Image(models.Model):
    image     = models.ImageField(upload_to='images/orig')
    thumbnail = models.ImageField(upload_to='images/thumbnails', editable=False)

    def save(self, *args, **kwargs):
       super(Image, self).save(*args, **kwargs)
       from core.tasks import create_thumbnail
       create_thumbnail.delay(self.id)

答案 1 :(得分:4)

您无需自行导入任务。尝试使用以下

from django.db import models
from celery.execute import send_task, delay_task

class Image(models.Model):
    image     = models.ImageField(upload_to='images/orig')
    thumbnail = models.ImageField(upload_to='images/thumbnails', editable=False)

    def save(self, *args, **kwargs):
       super(Image, self).save(*args, **kwargs)
       result = delay_task("task_prefix.create_thumbnail", post.id)

答案 2 :(得分:3)

我想知道问题是否可能是循环导入(modelstasks在顶层互相导入)。尝试将“from core.models import Image”移至create_thumbnail,即将tasks更改为

from celery.decorators import task

@task()
def create_thumbnail(image_id):
    from core.models import Image
    ImageObj = Image.objects.get(id=image_id)
    # other stuff here