Som @dotz nämnde , det är knappast användbart att skapa en asynkron uppgift och omedelbart blockera och fortsätta vänta tills den är klar.
Dessutom, om du kopplar till det på detta sätt (.get()
i slutet), kan du vara säker på att mymodel
instansändringar som just gjorts kommer inte att ses av din arbetare eftersom de inte kommer att begås ännu - kom ihåg att du fortfarande är inne i atomic
blockera.
Vad du kan göra istället (från Django 1.9) är att fördröja uppgiften tills efter att den aktuella aktiva transaktionen har genomförts, med django.db.transaction.on_commit
krok:
from django.db import transaction
with transaction.atomic():
mymodel.save()
transaction.on_commit(lambda:
mytask.delay(mymodel.id))
Jag använder det här mönstret ganska ofta i min post_save
signalhanterare som utlöser viss bearbetning av nya modellinstanser. Till exempel:
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))
På det här sättet kommer dock din uppgift inte att utföras om databastransaktionen misslyckas. Det är vanligtvis det önskade beteendet, men tänk på det.
Redigera :Det är faktiskt trevligare att registrera on_commit selleriuppgiften på detta sätt (utan lambda):
transaction.on_commit(tasks.process_new_order.s(instance.pk).delay)