Я работаю над проектом с использованием django и сельдерея (django-celery). Наша команда решила обернуть весь код доступа к данным в (app-name)/manager.py
(НЕ вписывать в менеджеры, как 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
каждый раз, и теперь единственное, что я могу сделать, это получить один тег.
Я новичок в декораторах. Кто-нибудь может помочь мне понять, что здесь пошло не так, или указать другие способы достижения этой цели? Мне очень не хочется писать один и тот же код переноса задачи для каждой из моих функций доступа к данным.