繁体   English   中英

Django 通道 WebSocket 参数

[英]Django Channels WebSocket argument

我正在尝试Django By Example, Chapter 13一书中的一个例子。 那里有一个示例,展示了稍后如何为聊天室建立套接字。 以下是我确定错误来自的代码:

room.html

{% extends "base.html" %}

{% block title %}Chat room for "{{ course.title }}"{% endblock %}

{% block content %}
  <div id="chat">
  </div>
  <div id="chat-input">
    <input id="chat-message-input" type="text">
    <input id="chat-message-submit" type="submit" value="Send">
  </div>
{% endblock %}

{% block domready %}
  var url = 'ws://' + window.location.host + '/ws/chat/room/' + '{{ course.id }}/';
  var chatSocket = new WebSocket(url);
{% endblock %}

下面是routing.pyconsumer.py

routing.py

from django.urls import re_path
from . import consumers

websocket_urlpatterns = [
    re_path(r'ws/chat/room/(?P<course_id>\d+)/$', consumers.ChatConsumer),
]

consumer.py

import json
from channels.generic.websocket import AsyncWebsocketConsumer

class ChatConsumer(AsyncWebsocketConsumer):
    def connect(self):
        self.accept()

    def disconnect(self, close_code):
        pass

    # receive message from WebSocket
    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        self.send(text_data=json.dumps({'message': message}))

以下是我在运行python manage.py runserver时收到的错误消息:

WebSocket HANDSHAKING /ws/chat/room/6/ [127.0.0.1:57288]
Exception inside application: object.__init__() takes exactly one argument (the instance to initialize)
Traceback (most recent call last):
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/staticfiles.py", line 44, in __call__
    return await self.application(scope, receive, send)
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/routing.py", line 71, in __call__
    return await application(scope, receive, send)
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/sessions.py", line 47, in __call__
    return await self.inner(dict(scope, cookies=cookies), receive, send)
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/sessions.py", line 254, in __call__
    return await self.inner(wrapper.scope, receive, wrapper.send)
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/auth.py", line 181, in __call__
    return await super().__call__(scope, receive, send)
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/middleware.py", line 26, in __call__
    return await self.inner(scope, receive, send)
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/routing.py", line 150, in __call__
    return await application(
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/asgiref/compatibility.py", line 33, in new_application
    instance = application(scope)
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/generic/websocket.py", line 159, in __init__
    super().__init__(*args, **kwargs)
TypeError: object.__init__() takes exactly one argument (the instance to initialize)

当我在模板room.html的块代码{% block domready %}中包含两行时,会发生此错误。 没有这两行,websocket 握手不会发生,因此不会出错。

从错误看来,套接字实例化只要求一个参数。 但似乎代码new WebSocket(url)确实给出了一个论点。 有谁知道是否缺少某些东西? 谢谢。

在@Iain Shevington 之后更新

以下是添加后的新错误消息

websocket_urlpatterns = [
    re_path(r'ws/chat/room/(?P<course_id>\d+)/$', consumers.ChatConsumer.as_asgi()),
]
WebSocket HANDSHAKING /ws/chat/room/6/ [127.0.0.1:57750]
Exception inside application: object NoneType can't be used in 'await' expression
Traceback (most recent call last):
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/staticfiles.py", line 44, in __call__
    return await self.application(scope, receive, send)
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/routing.py", line 71, in __call__
    return await application(scope, receive, send)
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/sessions.py", line 47, in __call__
    return await self.inner(dict(scope, cookies=cookies), receive, send)
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/sessions.py", line 254, in __call__
    return await self.inner(wrapper.scope, receive, wrapper.send)
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/auth.py", line 181, in __call__
    return await super().__call__(scope, receive, send)
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/middleware.py", line 26, in __call__
    return await self.inner(scope, receive, send)
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/routing.py", line 150, in __call__
    return await application(
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/consumer.py", line 94, in app
    return await consumer(scope, receive, send)
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/consumer.py", line 58, in __call__
    await await_many_dispatch(
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/utils.py", line 51, in await_many_dispatch
    await dispatch(result)
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/consumer.py", line 73, in dispatch
    await handler(message)
  File "/home/xxx/.local/share/virtualenvs/chat-ayPz2iC9/lib/python3.8/site-packages/channels/generic/websocket.py", line 175, in websocket_connect
    await self.connect()
TypeError: object NoneType can't be used in 'await' expression
WebSocket DISCONNECT /ws/chat/room/6/ [127.0.0.1:57750]

当您将消费者传递给websocket_urlpatterns时,您需要调用as_asgi()

websocket_urlpatterns = [
    re_path(r'ws/chat/room/(?P<course_id>\d+)/$', consumers.ChatConsumer.as_asgi()),
]

文档

我们在路由消费者时调用 as_asgi() 类方法。 这将返回一个 ASGI 包装应用程序,它将为每个连接或 scope 实例化一个新的消费者实例。 这类似于 Django 的 as_view(),它对基于类的视图的每个请求实例扮演相同的角色。

编辑:您正在使用异步消费者,异步消费者上的方法必须是协程(使用异步和等待)

class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        await self.accept()

    # receive message from WebSocket
    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        await self.send(text_data=json.dumps({'message': message}))

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM