strawberry-django-jwt
strawberry-django-jwt copied to clipboard
Async view raises `SynchronousOnlyOperation` when also logged into Django admin
i.e., when you have the sessionid
cookie.
The workaround is to log out of admin, or delete the sessionid
cookie.
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/graphql/execution/execute.py", line 521, in execute_field
result = resolve_fn(source, info, **args)
File "/usr/local/lib/python3.8/site-packages/strawberry_django_plus/optimizer.py", line 573, in resolve
ret = _next(root, info, *args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/strawberry_django_jwt/middleware.py", line 102, in resolve
user = authenticate(request=context, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/views/decorators/debug.py", line 42, in sensitive_variables_wrapper
return func(*func_args, **func_kwargs)
File "/usr/local/lib/python3.8/site-packages/django/contrib/auth/__init__.py", line 77, in authenticate
user = backend.authenticate(request, **credentials)
File "/usr/local/lib/python3.8/site-packages/strawberry_django_jwt/backends.py", line 11, in authenticate
return get_user_by_token(token, request)
File "/usr/local/lib/python3.8/site-packages/strawberry_django_jwt/shortcuts.py", line 30, in get_user_by_token
return get_user_by_payload(payload)
File "/usr/local/lib/python3.8/site-packages/strawberry_django_jwt/utils.py", line 169, in get_user_by_payload
user = jwt_settings.JWT_GET_USER_BY_NATURAL_KEY_HANDLER(username)
File "/usr/local/lib/python3.8/site-packages/strawberry_django_jwt/utils.py", line 150, in get_user_by_natural_key
return user_model.objects.get_by_natural_key(username)
File "/usr/local/lib/python3.8/site-packages/django/contrib/auth/base_user.py", line 46, in get_by_natural_key
return self.get(**{self.model.USERNAME_FIELD: username})
File "/usr/local/lib/python3.8/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
File "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", line 492, in get
num = len(clone)
File "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", line 302, in __len__
self._fetch_all()
File "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", line 1507, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "/usr/local/lib/python3.8/site-packages/django/db/models/query.py", line 57, in __iter__
results = compiler.execute_sql(
File "/usr/local/lib/python3.8/site-packages/django/db/models/sql/compiler.py", line 1359, in execute_sql
cursor = self.connection.cursor()
File "/usr/local/lib/python3.8/site-packages/django/utils/asyncio.py", line 24, in inner
raise SynchronousOnlyOperation(message)
django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context - use a thread or sync_to_async.
Hello, Thanks for submitting the issue.
It looks to me as if you were using the ASGI app with the synchronous jwt middleware. Could you please verify that this is the case?
@KundaPanda We are using AsyncStatusHandlingGraphQLView
with AsyncJSONWebTokenMiddleware
@KundaPanda We are using
AsyncStatusHandlingGraphQLView
withAsyncJSONWebTokenMiddleware
Okay so that seems in order.
Are you running the app with an ASGI-capable server as well (daphne, uvicorn, hypercorn)? This seems like the second most likely cause (i.e. with the runserver command or gunicorn).
We've encountered the issue with runserver and runserver_plus
Haven't deployed with uvicorn
yet.
Async seems to work though. I tested an API with asyncio.sleep(10)
and hit it in 2 tabs.
That explains it then. You need a proper ASGI server to send ASGI requests -- runserver and runserver_plus both serve WSGI only.
Internally this seems to work for you because Django creates a new loop for every incoming request. So you can have async views, but they are not actually running asynchronously. This also means that all Django middleware runs synchronously when processing requests. I will try to look into this and implement own asyncio loop creation in the middleware, but I do not consider this a bug/issue but rather a nice-to-have feature for debugging with runserver.
If you use channels runserver would be asgi so you can just add channels as dev requirement..
Tested with uvicorn. Same error.
CMD [ "uvicorn", "mysite.asgi:application", "--host=0.0.0.0", "--port=8000", "--reload" ]