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:
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?
1) Is what I'm trying to do considered a best practice? If yes, how do I work it out?
Yes, passing only a little information to the task is generally a good thing like you mentioned.
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?
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:
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)
i wonder if the problem might be a circular import (models
and tasks
importing each other at the top level). try moving "from core.models import Image
" into create_thumbnail
, i.e. changing tasks
to
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
You don't need to import the task itself. Try using the following
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)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With