Jak @dotz wspomniano , nie ma sensu tworzyć zadania asynchronicznego, natychmiast blokować i czekać, aż się zakończy.
Co więcej, jeśli dołączysz do niego w ten sposób (.get()
na końcu), możesz być pewien, że mymodel
dokonane właśnie zmiany instancji nie będą widoczne dla Twojego procesu roboczego, ponieważ nie zostaną jeszcze zatwierdzone — pamiętaj, że nadal znajdujesz się w atomic
blokować.
Zamiast tego możesz (od Django 1.9) opóźnić zadanie do momentu zatwierdzenia aktywnej transakcji, używając django.db.transaction.on_commit
hak:
from django.db import transaction
with transaction.atomic():
mymodel.save()
transaction.on_commit(lambda:
mytask.delay(mymodel.id))
Używam tego wzorca dość często w moim post_save
procedury obsługi sygnałów, które wyzwalają przetwarzanie nowych instancji modelu. Na przykład:
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))
W ten sposób jednak Twoje zadanie nie zostanie wykonane jeśli transakcja bazy danych nie powiedzie się. Zwykle jest to pożądane zachowanie, ale miej to na uwadze.
Edytuj :Właściwie fajniej jest zarejestrować zadanie selerowe on_commit w ten sposób (bez lambdy):
transaction.on_commit(tasks.process_new_order.s(instance.pk).delay)