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)
Вернуться на верх