Comme @dotz mentionné , il n'est guère utile de générer une tâche asynchrone et de la bloquer immédiatement et de continuer à attendre jusqu'à ce qu'elle se termine.
De plus, si vous l'attachez de cette façon (le .get()
à la fin), vous pouvez être sûr que le mymodel
les changements d'instance qui viennent d'être effectués ne seront pas vus par votre travailleur car ils ne seront pas encore validés - rappelez-vous que vous êtes toujours à l'intérieur du atomic
bloquer.
Ce que vous pourriez faire à la place (à partir de Django 1.9) est de retarder la tâche jusqu'à ce que la transaction active actuelle soit validée, en utilisant django.db.transaction.on_commit
crochet :
from django.db import transaction
with transaction.atomic():
mymodel.save()
transaction.on_commit(lambda:
mytask.delay(mymodel.id))
J'utilise ce modèle assez souvent dans mon post_save
des gestionnaires de signaux qui déclenchent le traitement de nouvelles instances de modèle. Par exemple :
from django.db import transaction
from django.db.models.signals import post_save
from django.dispatch import receiver
from . import models # Your models defining some Order model
from . import tasks # Your tasks defining a routine to process new instances
@receiver(post_save, sender=models.Order)
def new_order_callback(sender, instance, created, **kwargs):
""" Automatically triggers processing of a new Order. """
if created:
transaction.on_commit(lambda:
tasks.process_new_order.delay(instance.pk))
De cette façon, cependant, votre tâche ne sera pas exécutée si la transaction de base de données échoue. C'est généralement le comportement souhaité, mais gardez-le à l'esprit.
Modifier :Il est en fait plus agréable d'enregistrer la tâche de céleri on_commit de cette façon (sans lambda) :
transaction.on_commit(tasks.process_new_order.s(instance.pk).delay)