As @dotz vermeld , is het nauwelijks nuttig om een asynchrone taak te spawnen en onmiddellijk te blokkeren en te blijven wachten tot het klaar is.
Bovendien, als je het op deze manier (de .get()
aan het einde), kunt u er zeker van zijn dat de mymodel
zojuist aangebrachte wijzigingen in de instantie zullen niet worden gezien door uw werknemer omdat ze nog niet zijn vastgelegd - onthoud dat u zich nog steeds binnen de atomic
bevindt blok.
Wat je in plaats daarvan zou kunnen doen (vanaf Django 1.9) is de taak uitstellen tot nadat de huidige actieve transactie is vastgelegd, met behulp van django.db.transaction.on_commit
haak:
from django.db import transaction
with transaction.atomic():
mymodel.save()
transaction.on_commit(lambda:
mytask.delay(mymodel.id))
Ik gebruik dit patroon vrij vaak in mijn post_save
signaalhandlers die enige verwerking van nieuwe modelinstanties activeren. Bijvoorbeeld:
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))
Op deze manier wordt uw taak echter niet uitgevoerd als de databasetransactie mislukt. Het is meestal het gewenste gedrag, maar houd er rekening mee.
Bewerken :Het is eigenlijk leuker om de on_commit celery taak op deze manier te registreren (zonder lambda):
transaction.on_commit(tasks.process_new_order.s(instance.pk).delay)