Django + DRF + Celery: выполнение celery_task.delay() только после завершения транзакции базы данных (model.save() достигла базы данных)
Я пытался использовать метод on_commit, как они говорят нам в документации, но я все еще получаю ModelDoesNotExistError внутри задачи, запущенной через delay().
views.py:
class SomeViewset(viewsets.ModelViewset):
...
@action(detail=True, methods=['post'])
def some_action(self, request, *args, **kwargs):
m = MyModel()
with transaction.atomic():
m.save()
transaction.on_commit(lambda:
my_fav_task.delay(m.id, param2, param3))
return Response({"success": True, "operation_id": m.id}, status=status.HTTP_200_OK)
tasks.py:
@shared_task
def my_fav_task(operation_id, **params):
print(operation_id) # We get new id
print(MyModel.objects.all()) # No newly created object here
operation = MyModel.objects.get(id=operation_id) # Error here
Моя проблема была в неочевидном использовании разных баз данных между celery и django. Похоже, что контейнеры docker, выполняющие эти процессы, создавали локальные db каждый для себя, потому что я невольно использовал стандартную db.sqlite3 без специального разделения. После изменения настроек БД на postgre, которая была запущена в другом контейнере, заработала следующая схема:
from django.db import transactions
@transaction.atomic
def view(request):
m = MyModel()
m.save()
# Execute celery task only after database changes (m.save())
transaction.on_commit(lambda: my_fav_task.delay(m.id, param2, param3))
return Response({"success": True, "operation_id": m.id}, status=status.HTTP_200_OK)