Django - 通过模型中的 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
- 异常值: 无法导入名称任务
如果我注释掉,错误就会消失tasks.py
中的 from core.models import Image
,但这显然会导致问题,因为 Image
在这里没有任何意义。我尝试将其导入 create_thumbnail
内,但它仍然无法识别 Image
。
我在某处读到,通常对象本身可以作为参数传递给任务,这可以解决我的问题。然而,一位朋友曾经告诉我,在 RabbitMQ 消息中发送尽可能少的数据被认为是最佳实践,因此为了实现这一目标,我尝试仅传递图像 ID,然后在任务中再次检索它。
1)我正在尝试做的事情被认为是最佳实践吗?如果是,我该如何解决?
2)我注意到在网上找到的所有示例中,它们都是从视图而不是模型执行任务。我试图在上传新图像时创建缩略图,我不想在我拥有的每个表单/视图中调用 create_thumbnail 。对此有什么想法吗?不建议从模型执行任务还是常见做法?
In my 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)
In my 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
This is returning the following:
- Exception Type: ImportError
- Exception Value: cannot import name tasks
The error disappears if I comment out from core.models import Image
in tasks.py
, however this obviously will cause a problem since Image
has no meaning in here. I have tried to import it inside create_thumbnail
however it still won't recognize Image
.
I have read somewhere that usually the object itself can be passed as an argument to a task and that would solve my problem. However, a friend once told me that it is considered best practice to send as little data as possible in a RabbitMQ message, so to achieve that I'm trying to only pass the image ID and then retrieve it again in the task.
1) Is what I'm trying to do considered a best practice? If yes, how do I work it out?
2) I have noticed in all the examples I found around the web, they execute the task from a view and never from a model. I'm trying to create a thumbnail whenever a new image is uploaded, I don't want to call create_thumbnail in every form/view I have. Any idea about that? Is executing a task from a model not recommended or a common practice?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
是的,就像您提到的那样,仅向任务传递少量信息通常是一件好事。
我注意到了同样的事情,并且觉得教程和文档从他们的视图中调用任务,因为使用简单的视图比使用模型或表单更容易演示事物如何工作。
为了消除循环导入,您应该考虑应该以哪种方式导入。通常,tasks.py 需要从 models.py 导入许多内容,而 models.py 很少需要了解有关tasks.py 的任何信息。标准应该是models.py不从tasks.py导入。因此,如果您确实需要执行此操作并从模型方法调用任务,请按如下方式在方法中进行导入:
Yes, passing only a little information to the task is generally a good thing like you mentioned.
I've noticed the same thing, and feel that tutorials and documentation call tasks from their views because it is easier to demonstrate how things work using simple views than with models or forms.
To eliminate circular imports, you should think about which way the imports should happen. Generally, tasks.py will need to import many things from models.py whereas models.py rarely needs to know anything about tasks.py. The standard should be that models.py does not import from tasks.py. Thus, if you do need to do this and are calling a task from a model method, make the import in the method as so:
您不需要导入任务本身。尝试使用以下内容
You don't need to import the task itself. Try using the following
我想知道问题是否可能是循环导入(模型和任务在顶层相互导入)。尝试将“
from core.models import Image
”移动到create_thumbnail
,即将tasks
更改为i wonder if the problem might be a circular import (
models
andtasks
importing each other at the top level). try moving "from core.models import Image
" intocreate_thumbnail
, i.e. changingtasks
to