Django - 使用通道设置服务器发送事件:未处理的异常:SseConsumer() 缺少 2 个必需的位置参数:“接收”和“发送”

问题描述 投票:0回答:1

我有一个正在使用 websockets 的现有 Django Channels 设置,我必须添加另一个端点来支持 SSE。我按照这里的示例https://channels.readthedocs.io/en/stable/topics/consumers.html使用

AsyncHttpConsumer
设置消费者,但我收到了错误:

TypeError: ServerSentEventsConsumer() missing 2 required positional arguments: 'receive' and 'send'

我的设置如下:

playground/consumers.py

from datetime import datetime
from channels.generic.http import AsyncHttpConsumer

class ServerSentEventsConsumer(AsyncHttpConsumer):
    async def handle(self, body):
        await self.send_headers(headers=[
            (b"Cache-Control", b"no-cache"),
            (b"Content-Type", b"text/event-stream"),
            (b"Transfer-Encoding", b"chunked"),
        ])
        while True:
            payload = "data: %s\n\n" % datetime.now().isoformat()
            await self.send_body(payload.encode("utf-8"), more_body=True)
            await asyncio.sleep(1)

playground/asgi.py

import os
import django
from django.core.asgi import get_asgi_application

os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'playground.settings.production')
django.setup()
application = get_asgi_application()

playground/routing.py

from playground.asgi import application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator

from .consumers import (
    BaseConsumer,
    ServerSentEventsConsumer,
)
from django.urls import path, re_path

application = ProtocolTypeRouter(
    {
        "http": application,
        "websocket": AllowedHostsOriginValidator(
            JwtAuthMiddlewareStack(
                URLRouter(
                    [
                        re_path(r"^wss$", BaseConsumer),
                        re_path("sse", ServerSentEventsConsumer.as_asgi()) # <- Desperate attempt. I don't wanna use websockets.
                    ]
                )
            )
        ),
    }
)

playground/urls.py

urlpatterns = [
    path("sse/", ServerSentEventsConsumer.as_asgi(), name="sse")
]

我使用以下软件版本:

asgiref = "3.7.2"
Django = "4.0.10"
channels-redis = "4.1.0"
channels = "4.0.0"

我见过一些相关问题,人们通过将 Channels 降级到版本 3 来解决这些问题。这对我来说不是一个选择,因为首先要升级到 Django 4 是团队的主要工作。

任何意见都将受到高度赞赏。


更新#1

我尝试将

Channels
降级到较低版本,但仍然遇到相同的错误:

asgiref = "3.7.2"
channels = "3.0.5"
channels-redis = "3.4.1"
daphne = "3.0.2"
django django-channels asgi django-4.0
1个回答
0
投票

我最终通过进行以下更改成功地完成了这项工作:

playground/routing.py

from playground.asgi import application
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator

from .consumers import (
    BaseConsumer,
    ServerSentEventsConsumer,
)
from django.urls import path, re_path

application = ProtocolTypeRouter(
    {
-       "http": application, # <-- removed this
+       "http": URLRouter([
+           path("sse/<str:username>": ServerSentEventsConsumer.as_asgi()),
+           path(r"", application),
+       ]),
        "websocket": AllowedHostsOriginValidator(
            JwtAuthMiddlewareStack(
                URLRouter(
                    [
                        re_path(r"^wss$", BaseConsumer)
                    ]
                )
            )
        ),
    }
)
© www.soinside.com 2019 - 2024. All rights reserved.