Редко возникает ошибка SynchronousOnlyOperation в различных GET запросах, содержащих запрос к базе данных в Django 3.2.6
Ошибка возникает только в среде сервера разработки, не могу воспроизвести ее на локальном. Сервер разработки - это docker composed среда с Django 3.2.6, python 3.7, gunicorn (для wsgi), daphne (для asgi), postgres 12, redis, celery & celery-beat inside.
Ошибка происходит в GET запросах, которые не должны иметь асинхронного контекста.
Например, лог одной из этих ошибок:
, представление api выглядит как
class GroupsView(BaseSyncView):
queryset = GroupModel.all_objects.all()
serializer_class = GroupSerializer
enter code here
class BaseSyncView(mixins.ListModelMixin,
mixins.CreateModelMixin,
mixins.DestroyModelMixin,
mixins.RetrieveModelMixin,
GenericAPIView):
serializer_class = BaseSyncSerializer # Virtual, to override
queryset = None # Virtual, to override
lookup_field = 'uuid'
def get(self, request, *args, **kwargs):
return self.list_retrieve(request, *args, **kwargs)
...
Другой пример, для упрощения - логи указывают на строку в стандартном drf APIView:
book: BookModel = BookModel.objects.get_with_raise(uuid=uuid, deleted_at__isnull=True)
Модель книги имеет переопределенный менеджер
class Manager(DjangoBaseManager.from_queryset(BaseQuerySet)):
def __init__(self, *args, **kwargs):
self.alive_only = kwargs.pop('alive_only', True)
super(Manager, self).__init__(*args, **kwargs)
def get_queryset(self, *args, **kwargs):
if self.alive_only:
return super().get_queryset(*args, **kwargs).filter(deleted_at=None)
return super().get_queryset(*args, **kwargs)
class BaseQuerySet(models.QuerySet):
def get_with_raise(self, *args, **kwargs):
try:
return super().get(*args, **kwargs)
except self.model.DoesNotExist:
kwargs_string = ", ".join(f"{key}={value}" for key, value in kwargs.items())
raise EntityDoesNotExistException(reason=f'{self.model.__name__} with {kwargs_string} not found')
except Exception as ex:
raise InternalServerException(str(ex))
Любые советы приветствуются, спасибо.
Что произойдет, если вы получите доступ к ресурсу, обратившись непосредственно к БД, без использования ORM? Django ORM не позволяет асинхронный доступ. Попробуйте реализовать sync_to_async в вашем представлении.