Je travaille sur un projet utilisant django et celery(django-celery). Notre équipe a décidé d'envelopper tout le code d'accès aux données au sein de (app-name)/manager.py
(PAS d'enveloppement dans les Managers comme le django
), et laisser le code dans (nom de l'application)/task.py s'occuper uniquement de l'assemblage et de l'exécution des tâches avec celery (ainsi nous n'avons pas de dépendance ORM de django dans cette couche).
Dans mon manager.py
j'ai quelque chose comme ça :
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()
Dans mon task.py, j'aime les envelopper dans des tâches (puis peut-être utiliser ces tâches pour faire des tâches plus compliquées), donc j'écris ce décorateur :
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
puis (toujours dans 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
Tout fonctionne bien sans @task
. Mais, après avoir appliqué cette @task
décorateur (en haut comme la documentation sur le céleri l'indique), les choses commencent à s'écrouler. Apparemment, chaque fois que le mfunc_to_task.__call__
est appelé, le même task.get_tag
est passée comme f
. Donc je me suis retrouvé avec le même wrapper_f
à chaque fois, et maintenant la seule chose que je peux faire est d'obtenir une seule étiquette.
Je suis nouveau chez les décorateurs. Quelqu'un peut-il m'aider à comprendre ce qui n'a pas fonctionné ici, ou m'indiquer d'autres moyens d'accomplir cette tâche ? Je déteste vraiment écrire le même code d'enveloppement des tâches pour chacune de mes fonctions d'accès aux données.