2011-11-12 15 views
8

W moim models.py:Django - Wykonywanie zadań przez selera z modelu

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) 

W moim 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 

Ten wraca następujące:

  • Typ wyjątku: ImportError
  • Wyjątek Wartość: nie może importować zadania nazw

Błąd znika gdybym wykomentuj from core.models import Image w tasks.py jednak to oczywiście spowoduje problem ponieważ Image ma znaczenia tutaj. Próbowałem zaimportować go wewnątrz create_thumbnail, ale nadal nie rozpoznaje Image.

Czytałem gdzieś, że zwykle sam obiekt może zostać przekazany jako argument do zadania i to rozwiąże mój problem. Jednak znajomy powiedział mi kiedyś, że najlepszą praktyką jest wysyłanie możliwie jak najmniejszej ilości danych w wiadomości RabbitMQ, więc w tym celu próbuję jedynie przekazać identyfikator obrazu, a następnie pobrać go ponownie w zadaniu.

1) Czy to, co próbuję zrobić, jest uważane za najlepszą praktykę? Jeśli tak, jak mogę to rozwiązać?

2) Zauważyłem we wszystkich przykładach znalezionych w Internecie, wykonują zadanie z widoku, a nigdy z modelu. Próbuję utworzyć miniaturę za każdym razem, gdy nowy obraz zostanie przesłany, nie chcę wywoływać create_thumbnail w każdej formie/widoku, jaki mam. Masz jakiś pomysł? Czy wykonywanie zadania z modelu nie jest zalecane lub powszechna praktyka?

Odpowiedz

13

1) Is what I'm trying to do considered a best practice? If yes, how do I work it out?

Tak, przechodząc tylko trochę informacji do zadania jest ogólnie dobra rzecz jak wspomniałeś.

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?

Zauważyłem to samo, i czuję, że ćwiczenia i zadania połączeń dokumentacja z ich poglądów, ponieważ łatwiej jest pokazać, jak to wszystko działa za pomocą prostych widoki niż z modeli lub form.

Aby wyeliminować cykliczne importowanie, należy zastanowić się, w jaki sposób powinien nastąpić import. Ogólnie rzecz biorąc, tasks.py będzie musiał zaimportować wiele rzeczy z models.py podczas gdy models.py rzadko musi wiedzieć cokolwiek na temat tasks.py. Standardem powinno być to, że model .py nie importuje z pliku tasks.py. Tak więc, jeśli trzeba to zrobić i wzywają zadania z metody modelu sprawiają, że import w sposób jak w przykładzie:

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

Naprawdę doceniłem akapit" Aby wyeliminować import okrężny, należy zastanowić się, w jaki sposób powinien nastąpić przywóz ... ". Dziękuję Ci. – pawelmech

1

Zastanawiam się, czy problem może dotyczyć importu kołowego (models i tasks importowanie się nawzajem na najwyższym poziomie). spróbuj przenieść „from core.models import Image” do create_thumbnail, to znaczy zmienia tasks do

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 
+0

Próbowałem już, że w tym przypadku wiadomość zostanie wysłana poprawnie jednak create_thumbnail generuje błąd: '„/home/ubuntu/project/core/tasks.py”Plik linię 5, in create_thumbnail' 'from core.models import Image' ' NameError: nazwa globalna 'Obraz' nie jest zdefiniowany ' – abstractpaper

+0

Zakładam' core' to nazwa twojej aplikacji. czy próbowałeś poprzedzać nazwę projektu (np. 'from project.app.models import Model')? django używa jakiejś magii ścieżki, która czasami jest mniej pomocna. – second

+0

Po prostu wykonałem ten sam błąd: 'NameError: nazwa globalna 'Image' is not defined'. Mam już dołączoną ścieżkę projektu do 'django.wsgi'. – abstractpaper

4

Nie trzeba importować samego zadania.Spróbuj użyć następującego

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) 
+1

selera.execute już nie istnieje w selerze 3.x – Titusz