2011-11-12 11 views
8

からセロリを通じてタスクを実行Djangoは私のmodels.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
  • 例外値:は、名前のタスク

私はImageはここでは意味がありませんので、しかし、これは明らかに問題が発生します、tasks.pyfrom core.models import Imageをコメントアウトした場合、エラーが消えるをインポートすることはできません。私はcreate_thumbnailの中でそれをインポートしようとしましたが、まだそれはImageを認識しません。

私は、通常、オブジェクト自体をタスクの引数として渡すことができますが、それは私の問題を解決するだろうと読んでいます。しかし、友人は一度、RabbitMQメッセージにできるだけ少ないデータを送信することをお勧めしています。そのため、イメージIDを渡してからタスクで再度取得しようとしています。

1)私がしようとしていることがベストプラクティスと考えられていますか?はいの場合、どうすればうまくいくのですか?

2)私はWeb上で見つかったすべての例で気づきましたが、彼らはビューから、そしてモデルから決してそのタスクを実行しません。新しい画像がアップロードされるたびにサムネイルを作成しようとしていますが、フォーム/ビューごとにcreate_thumbnailを呼びたくありません。それについてのアイデア?推奨されていないモデルや一般的なプラクティスからタスクを実行していますか?

答えて

13

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?

私は同じことに気づいた、との見解から、チュートリアルやドキュメンテーション呼び出しタスクは、モデルやフォームでよりシンプルなビューを使用して、物事がどのように働くかを証明することが容易であるため、と感じました。

循環インポートを排除するには、どのようなインポートが行われるべきかを考える必要があります。一般に、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) 
+1

私は本当に「循環輸入を排除するには、どのような輸入が起こるべきかを考えなければならない」というパラグラフを高く評価しました。ありがとうございました。 – pawelmech

1

問題が循環インポート(modelstasksが最上位レベルでインポートされている)である可能性があります。あなたが言及したように、一般的には良いことがある、すなわち、create_thumbnailに「from core.models import Image」移動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 
+0

を使用してみてください5、in create_thumbnail' 'from core.models import Image' ' NameError:グローバル名 'Image'が定義されていません。 – abstractpaper

+0

'core'はあなたのアプリケーションの名前です。あなたはプロジェクト名を前もって試してみましたか(つまり、 'project.app.models import Model'から'? djangoは役に立つかもしれないいくつかのパスマジックを行う場合があります – second

+0

同じエラーが返されました: 'NameError:グローバル名 'Image'が定義されていません。私は既に 'django.wsgi'にプロジェクトパスを追加しています。 – abstractpaper

4

あなたはタスク自体をインポートする必要はありません。 `ファイル「/home/ubuntu/project/core/tasks.py」を、行を:create_thumbnailでエラーが発生したが、私はすでにこのような場合にはメッセージが正しく送信された、ことを試してみましたが、次の

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

セロリー3.xでcelery.executeがもう存在しないようです – Titusz

関連する問題