2011-11-12 3 views
8

Nel mio models.py:Django - L'esecuzione di un compito attraverso sedano da un modello

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) 

Nel mio 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 

Questo sta tornando il seguente:

  • Tipo eccezione: ImportErrore
  • Eccezione Valore: non può importare compiti nome

L'errore scompare se io commento from core.models import Image in tasks.py, tuttavia questo ovviamente causerà un problema dato Image non ha senso qui. Ho provato a importarlo all'interno di create_thumbnail tuttavia non lo riconoscerà ancora Image.

Ho letto da qualche parte che in genere l'oggetto stesso può essere passato come argomento a un'attività e che risolverebbe il mio problema. Tuttavia, una volta un amico mi ha detto che è considerata una buona pratica inviare il minor numero di dati possibile in un messaggio RabbitMQ, così per realizzare che sto provando a passare solo l'ID dell'immagine e poi a recuperarla nuovamente nell'attività.

1) È quello che sto cercando di fare considerato una buona pratica? Se sì, come posso risolverlo?

2) Ho notato in tutti gli esempi che ho trovato in tutto il Web, che eseguono l'attività da una vista e mai da un modello. Sto provando a creare una miniatura ogni volta che viene caricata una nuova immagine, non voglio chiamare create_thumbnail in ogni forma/vista che ho. Qualche idea al riguardo? Esecuzione di un'attività da un modello non consigliato o da una pratica comune?

risposta

13

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

Sì, passando solo un po 'di informazioni per il compito è generalmente una buona cosa, come lei ha ricordato.

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?

ho notato la stessa cosa, e ritengono che i tutorial e le attività di chiamata documentazione dal loro punto di vista, perché è più facile dimostrare come funzionano le cose utilizzando le visualizzazioni semplici rispetto ai modelli o forme.

Per eliminare le importazioni circolari, è necessario valutare in che modo dovrebbero avvenire le importazioni. Generalmente, tasks.py dovrà importare molte cose da models.py mentre models.py ha raramente bisogno di sapere qualcosa su tasks.py. Lo standard dovrebbe essere quello che model.py non importa da tasks.py. Quindi, se si ha bisogno di fare questo e sta chiamando un compito da un metodo del modello, effettuare l'importazione nel metodo come così:

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

Ho davvero apprezzato il paragrafo" Per eliminare le importazioni circolari, dovresti pensare a quale modo le importazioni dovrebbero accadere ... ". Grazie. – pawelmech

1

Mi chiedo se il problema potrebbe essere un'importazione circolare (models e tasks l'importazione a vicenda al livello superiore). provare a spostare "from core.models import Image" in create_thumbnail, cioè cambiando tasks a

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

ho già provato che, in questo caso il messaggio viene inviato correttamente tuttavia create_thumbnail genera un errore: 'File "/home/ubuntu/project/core/tasks.py", linea 5, in create_thumbnail' 'da core.models import Image' ' NameError: nome globale 'Immagine' non è definito' – abstractpaper

+0

presumo 'core' è il nome della tua app. hai provato ad anteporre il nome del progetto (cioè 'da project.app.models import Model')? django fa qualche percorso magico che a volte è meno utile – second

+0

Appena fatto, lo stesso errore restituito: 'NameError: nome globale 'Immagine' non è definito'. Ho già aggiunto il mio percorso di progetto in 'django.wsgi'. – abstractpaper

4

Non è necessario importare il compito stesso.Provare a utilizzare il seguente

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

celery.execute non sembra più esistere in sedano 3.x – Titusz