TL;DR
After an upgrade to Django 3.2, using the Channels deprecated method for ASGI handling works. Using the new recommended method doesn't work.
I'm upgrading from Django 3.0/Channels 2 to Django 3.2/Channels 3.
In channels 3.0 release notes, it is stated that instantiating a ProtocolRouter
without the http
key is deprecated, and that one should use django.core.asgi.get_asgi_application
as value.
However, when I'm explicit on the http
protocol using get_asgi_application
, my middlewares don't work anymore: the app is complaining that I'm using sync middleware in an async context. This is the Django error popping up:
SynchronousOnlyOperation at /graphql/
You cannot call this from an async context - use a thread or sync_to_async.
...
The full traceback is here: https://pastebin.com/chRyW4VL
Here is the content of asgi.py
# my_project/asgi.py
import os
from channels.routing import ProtocolTypeRouter, URLRouter
import django
from django.core.asgi import get_asgi_application
assert os.environ.get('DJANGO_SETTINGS_MODULE') is not None, \
'The `DJANGO_SETTINGS_MODULE` env var must be set.'
django.setup()
from core.urls import ws_routes
application = ProtocolTypeRouter({
# If the following line is not commented out, I get the above error.
# 'http': get_asgi_application(),
'websocket': URLRouter(ws_routes)
})
[EDIT] Here is a snippet of the middleware causing the issue:
# core/middleware.py
class MyMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
...
response = self.get_response(request) # THIS LINE CAUSES THE ERROR
...
return response
# Down the traceback, the culprit is a database call:
# core/**/another_module.py
def get_user_by_id(uid):
return User.objects.get(id=uid) # BOOM!
"""
I know this db call is synchronous, but this is fine:
I don't want it to be something else. I only want to
use it in standard HTTP request/response cycle, with synchronous views, etc.
"""
I do not want to use async logic in my HTTP handlers/middleware, as I prefer the simplicity of synchronous patterns. I use Channels only to deal with websockets.
I'm looking for advice on how to follow Channels guidelines (ie, be explicit about the http
protocol application).
In the meantime, I simply ignore the deprecation warning, and use the ASGI handler offered by Channels.