2011-09-08 2 views
5

Je veux exécuter une tâche Django - Celery avec la gestion manuelle des transactions, mais il semble que les annotations ne s'empilent pas.Django - Celery: @transaction et @task ne s'empilent pas

par exemple.

def ping(): 
    print 'ping' 
    pong.delay('arg') 

@task(ignore_result=True) 
@transaction.commit_manually() 
def pong(arg): 
    print 'pong: %s' % arg 
    transaction.rollback() 

résultats dans

TypeError: pong() got an unexpected keyword argument 'task_name' 

alors que les résultats de l'ordre d'annotation inverse dans

---> 22  pong.delay('arg') 

AttributeError: 'function' object has no attribute 'delay' 

Il est logique, mais je vais avoir du mal à trouver une solution agréable. Les docs Django ne mentionnent pas d'alternatives à l'annotation, et je ne veux pas faire de classe pour chaque tâche de céleri quand je n'en ai pas besoin.

Des idées?

Répondre

8

Auparavant Céleri avait un peu de magie où un ensemble d'arguments de mots clés par défaut ont été transmis à la tâche si elle les a acceptées.

Depuis la version 2.2, vous pouvez désactiver ce comportement, mais le plus simple est de importer le décorateur task de celery.task au lieu de celery.decorators:

from celery.task import task 

@task 
@transaction.commit_manually 
def t(): 
    pass 

Le module decorators est dépréciée et sera complètement supprimé dans la version 3.0, et la même chose pour les "arguments de mots-clés magiques"

Remarque: Pour les classes de tâches personnalisées, vous devez définir l'attribut accept_magic_kwargs sur False:

class MyTask(Task): 
    accept_magic_kwargs = False 

Note2: Assurez-vous que vos décorateurs personnalisés conserve le nom de la fonction à l'aide functools.wraps, sinon la tâche finira avec le mauvais nom.

+0

C'est exactement ce que j'espérais! Merci! – Rob

6

Le décorateur de tâches génère un class x(Task) à partir de votre fonction avec la méthode run comme cible. Suggérez-vous de définir la classe et décorer la méthode.

.: Non testé par exemple

class pong(Task): 
    ignore_result = True 

    @transaction.commit_manually() 
    def run(self,arg,**kwargs): 
    print 'pong: %s' % arg 
    transaction.rollback() 
+0

Espérait trouver une façon non-classe de le faire, mais je suppose que c'est la meilleure alternative. Merci! – Rob

Questions connexes