Джанго - Выполнение задания с помощью сельдерея из модели - PullRequest
9 голосов
/ 12 ноября 2011

В моих моделях.

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)

В моих задачах.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, поэтому для этого я пытаюсь только передать идентификатор изображения, а затем снова получить его в задаче. *

1) То, что я пытаюсь сделать, считается лучшей практикой? Если да, то как мне это решить?

2) Я заметил, что во всех примерах, найденных в Интернете, они выполняют задачу из представления, а не из модели. Я пытаюсь создать миниатюру всякий раз, когда загружается новое изображение, я не хочу вызывать create_thumbnail в каждой форме / представлении, которое у меня есть. Есть идеи по этому поводу? Выполнение задачи из модели не рекомендуется или является обычной практикой?

Ответы [ 3 ]

14 голосов
/ 13 ноября 2011

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)
4 голосов
/ 13 ноября 2011

Вам не нужно импортировать само задание. Попробуйте использовать следующее

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)
3 голосов
/ 12 ноября 2011

Интересно, может ли проблема заключаться в круговом импорте (models и tasks, импортирующем друг друга на верхнем уровне).попробуйте переместить "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
...