【问题标题】:Django 3.2 `get_asgi_application` is not a replacement for channels AsgiHandlerDjango 3.2 `get_asgi_application` 不是通道 AsgiHandler 的替代品
【发布时间】:2021-09-10 05:51:12
【问题描述】:

TL;DR

升级到 Django 3.2 后,使用不推荐使用的 Channels 方法进行 ASGI 处理工作。使用新的推荐方法不起作用。


我正在从 Django 3.0/Channels 2 升级到 Django 3.2/Channels 3。

在频道 3.0 release notes 中,声明不推荐使用不带 http 键的 ProtocolRouter 实例化,并且应该使用 django.core.asgi.get_asgi_application 作为值。

然而,当我使用 get_asgi_application 明确使用 http 协议时,我的中间件不再工作:应用程序抱怨我在异步中使用同步中间件语境。这是弹出的Django错误:

SynchronousOnlyOperation at /graphql/
You cannot call this from an async context - use a thread or sync_to_async.

...

完整的追溯在这里:https://pastebin.com/chRyW4VL

这里是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)
})

[编辑] 这是导致问题的中间件的 sn-p:

# 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.
"""

我不想在我的 HTTP 处理程序/中间件中使用异步逻辑,因为我更喜欢同步模式的简单性。我只使用 Channels 来处理 websockets。

我正在寻求有关如何遵循频道指南的建议(即明确说明 http 协议应用程序)。

同时,我只是忽略弃用警告,并使用 Channels 提供的 ASGI 处理程序。

【问题讨论】:

  • 这很有趣。您是否使用 Daphne 来同时处理 WebSocket 和正常请求?您能否还显示导致问题的中间件?快速浏览源代码会发现 Django 应该使任何中间件适应“正确”模式,所以问题可能出在中间件本身
  • 确实,这两种情况都使用了达芙妮。我编辑了我的原始帖子以共享导致问题的中间件:它只是将当前用户存储在一个上下文变量中,可供整个应用程序使用。
  • 能否包含回溯?如果有问题的行是self.get_response,它似乎与这个确切的中间件无关。如果删除此中间件,错误会消失吗?
  • 请查看我更新的帖子,了解有关回溯的更多信息。是的,删除此中间件后错误消失。
  • 谢谢,不幸的是,我还是不明白。由于错误发生在self.get_response 上,这意味着它与此中间件无关,但是如果您删除它,错误就会消失

标签: django django-channels asgi


【解决方案1】:

正如this GitHub issue 中所讨论的,问题来自 Django,并在this ticket 中进行了描述。

this PR 合并并在 Django 中发布后应立即修复。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-02
    • 1970-01-01
    • 2015-06-15
    • 2021-09-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多