私はdjangoとセロリ(django-celery)を使ったプロジェクトに取り組んでいます。私たちのチームは、すべてのデータ アクセス コードを(app-name)/manager.py
(このように Manager にラップするのではなくdjango
) ラップし、コードを (app-name)/task.py に配置して、セロリを使用したタスクのアセンブルと実行のみを処理することにしました (したがって、django はありません)。このレイヤーの ORM 依存関係)。
私manager.py
の には、次のようなものがあります。
def get_tag(tag_name):
ctype = ContentType.objects.get_for_model(Photo)
try:
tag = Tag.objects.get(name=tag_name)
except ObjectDoesNotExist:
return Tag.objects.none()
return tag
def get_tagged_photos(tag):
ctype = ContentType.objects.get_for_model(Photo)
return TaggedItem.objects.filter(content_type__pk=ctype.pk, tag__pk=tag.pk)
def get_tagged_photos_count(tag):
return get_tagged_photos(tag).count()
私の task.py では、それらをタスクにラップするのが好きです (その後、これらのタスクを使用してより複雑なタスクを実行する可能性があります)。そのため、次のデコレータを記述します。
import manager #the module within same app containing data access functions
class mfunc_to_task(object):
def __init__(mfunc_type='get'):
self.mfunc_type = mfunc_type
def __call__(self, f):
def wrapper_f(*args, **kwargs):
callback = kwargs.pop('callback', None)
mfunc = getattr(manager, f.__name__)
result = mfunc(*args, **kwargs)
if callback:
if self.mfunc_type == 'get':
subtask(callback).delay(result)
elif self.mfunc_type == 'get_or_create':
subtask(callback).delay(result[0])
else:
subtask(callback).delay()
return result
return wrapper_f
次に (まだtask.py
):
#@task
@mfunc_to_task()
def get_tag():
pass
#@task
@mfunc_to_task()
def get_tagged_photos():
pass
#@task
@mfunc_to_task()
def get_tagged_photos_count():
pass
なしでも問題なく動作し@task
ます。しかし、その@task
デコレータを(セロリのドキュメントで指示されているように一番上に)適用した後、物事はバラバラになり始めます。どうやら、 が呼び出されるたびmfunc_to_task.__call__
に、同じtask.get_tag
関数が として渡されf
ます。wrapper_f
そのため、毎回同じ結果になりましたが、今では、単一のタグを取得することしかできません。
私はデコレータが初めてです。ここで何がうまくいかなかったのかを理解するのを手伝ってくれる人、またはタスクを達成するための他の方法を指摘してくれる人はいますか? 私は、すべてのデータ アクセス関数に対して同じタスク ラップ コードを記述するのが本当に嫌いです。