django-celery-transactions holds on to Celery tasks until the current database transaction is committed, avoiding potential race conditions as described in Celery's user guide. Send tasks from signal handlers without fear!
- If the transaction is rolled back, the tasks are discarded. Django's transaction middleware does this if an exception is raised.
- If transactions aren't being managed, tasks are sent as normal. This means
that sending tasks from within Django's shell will work as expected, as will
the various transaction decorators
Installation & Use
Install django-celery-transactions from PyPI:
$ pip install django-celery-transactions
Use the patched decorator to create your tasks:
from djcelery_transactions import task from models import Model @task def print_model(model_pk): print Model.objects.get(pk=model_pk)
Then use them as normal:
from django.db import transaction from models import Model from tasks import print_model # This task will be sent after the transaction is committed. This works # from anywhere in the managed transaction block (e.g. signal handlers). def view(request): model = Model.objects.create(...) print_model.delay(model.pk) # This task will not be sent (it is discarded) as the transaction # middleware rolls the transaction back when it catches the exception. def failing_view(request, model_pk): print_model.delay(model_pk) raise Exception() # This task will be sent immediately as transactions aren't being # managed and it is assumed that the author knows what they're doing. @transaction.commit_manually def manual_view(request, model_pk): print_model.delay(model_pk) transaction.commit()