【问题标题】:TypeError: object.__init__() takes exactly one argument (the instance to initialize) WebSocket DISCONNECT /public_chat/1/ [127.0.0.1:50083]TypeError: object.__init__() 只接受一个参数(要初始化的实例) WebSocket DISCONNECT /public_chat/1/ [127.0.0.1:50083]
【发布时间】:2021-04-16 08:02:46
【问题描述】:

我正在关注Coding With Mitch 聊天应用,但遇到了错误。

当我运行服务器时,它工作正常,但是当我刷新浏览器时它会显示

TypeError: object.init() 只接受一个参数(要初始化的实例) WebSocket DISCONNECT /public_chat/1/ [127.0.0.1:50083]

settings.py

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [('127.0.0.1', 6379)],
        },
    },
}

路由.py

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator
from django.urls import path, re_path

from chat.consumers import ChatConsumer
from public_chat.consumers import PublicChatConsumer
from notification.consumers import NotificationConsumer


application = ProtocolTypeRouter({
    'websocket': AllowedHostsOriginValidator(
        AuthMiddlewareStack(
            URLRouter([
                    re_path('', NotificationConsumer.as_asgi()),
                    re_path('chat/<room_id>/', ChatConsumer.as_asgi()),
                    re_path('public_chat/<room_id>/', PublicChatConsumer.as_asgi()),
            ])
        )
    ),
})

websockets.py

import json

from asgiref.sync import async_to_sync

from ..consumer import AsyncConsumer, SyncConsumer
from ..exceptions import (
    AcceptConnection,
    DenyConnection,
    InvalidChannelLayerError,
    StopConsumer,
)


class WebsocketConsumer(SyncConsumer):

groups = None

    def __init__(self, *args, **kwargs):
       if self.groups is None:
            self.groups = []

    def websocket_connect(self, message):

        try:
            for group in self.groups:
                async_to_sync(self.channel_layer.group_add)(group, 
self.channel_name)
        except AttributeError:
            raise InvalidChannelLayerError(
                "BACKEND is unconfigured or doesn't support groups"
            )
            try:
            self.connect()
        except AcceptConnection:
            self.accept()
        except DenyConnection:
            self.close()

    def connect(self):
        self.accept()

    def accept(self, subprotocol=None):

    super().send({"type": "websocket.accept", "subprotocol": subprotocol})

    def websocket_receive(self, message):

        if "text" in message:
            self.receive(text_data=message["text"])
        else:
            self.receive(bytes_data=message["bytes"])

        def receive(self, text_data=None, bytes_data=None):
  
        pass

    def send(self, text_data=None, bytes_data=None, close=False):

        if text_data is not None:
            super().send({"type": "websocket.send", "text": text_data})
        elif bytes_data is not None:
            super().send({"type": "websocket.send", "bytes": bytes_data})
        else:
            raise ValueError("You must pass one of bytes_data or text_data")
        if close:
            self.close(close)

    def close(self, code=None):

        if code is not None and code is not True:
            super().send({"type": "websocket.close", "code": code})
        else:
            super().send({"type": "websocket.close"})

    def websocket_disconnect(self, message):

        try:
            for group in self.groups:
                async_to_sync(self.channel_layer.group_discard)(
                    group, self.channel_name
                )
        except AttributeError:
            raise InvalidChannelLayerError(
                "BACKEND is unconfigured or doesn't support groups"
            )
        self.disconnect(message["code"])
        raise StopConsumer()

    def disconnect(self, code):

        pass


class JsonWebsocketConsumer(WebsocketConsumer):


    def receive(self, text_data=None, bytes_data=None, **kwargs):
         if text_data:
            self.receive_json(self.decode_json(text_data), **kwargs)
        else:
            raise ValueError("No text section for incoming WebSocket frame!")

     def receive_json(self, content, **kwargs):
 
        pass

    def send_json(self, content, close=False):
 
        super().send(text_data=self.encode_json(content), close=close)

    @classmethod
    def decode_json(cls, text_data):
        return json.loads(text_data)

    @classmethod
    def encode_json(cls, content):
        return json.dumps(content)


class AsyncWebsocketConsumer(AsyncConsumer):


    groups = None

    def __init__(self, *args, **kwargs):
        super().__init__(self,*args, **kwargs)
        if self.groups is None:
            self.groups = []

    async def websocket_connect(self, message):
 
      try:
            for group in self.groups:
                await self.channel_layer.group_add(group, self.channel_name)
        except AttributeError:
            raise InvalidChannelLayerError(
                "BACKEND is unconfigured or doesn't support groups"
            )
        try:
            await self.connect()
        except AcceptConnection:
            await self.accept()
        except DenyConnection:
            await self.close()

    async def connect(self):
        await self.accept()

    async def accept(self, subprotocol=None):
 
        await super().send({"type": "websocket.accept", "subprotocol": subprotocol})

    async def websocket_receive(self, message):
 
       if "text" in message:
            await self.receive(text_data=message["text"])
        else:
            await self.receive(bytes_data=message["bytes"])

    async def receive(self, text_data=None, bytes_data=None):
  
        pass

    async def send(self, text_data=None, bytes_data=None, close=False):

        if text_data is not None:
            await super().send({"type": "websocket.send", "text": text_data})
        elif bytes_data is not None:
            await super().send({"type": "websocket.send", "bytes": bytes_data})
        else:
            raise ValueError("You must pass one of bytes_data or text_data")
        if close:
            await self.close(close)

    async def close(self, code=None):
   
       if code is not None and code is not True:
            await super().send({"type": "websocket.close", "code": code})
        else:
            await super().send({"type": "websocket.close"})

    async def websocket_disconnect(self, message):

        try:
            for group in self.groups:
                await self.channel_layer.group_discard(group, self.channel_name)
         except AttributeError:
            raise InvalidChannelLayerError(
                "BACKEND is unconfigured or doesn't support groups"
            )
        await self.disconnect(message["code"])
        raise StopConsumer()

    async def disconnect(self, code):

        pass


class AsyncJsonWebsocketConsumer(AsyncWebsocketConsumer):


    async def receive(self, text_data=None, bytes_data=None, **kwargs):
        if text_data:
            await self.receive_json(await self.decode_json(text_data), **kwargs)
        else:
            raise ValueError("No text section for incoming WebSocket frame!")

    async def receive_json(self, content, **kwargs):

        pass

    async def send_json(self, content, close=False):
    """
    Encode the given content as JSON and send it to the client.
    """
    await super().send(text_data=await self.encode_json(content), close=close)

@classmethod
async def decode_json(cls, text_data):
    return json.loads(text_data)

@classmethod
async def encode_json(cls, content):
    return json.dumps(content)

settings.py:

ASGI_APPLICATION = 'brain.routing.application'

CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [('127.0.0.1', 6379)],
        },
    },
}

当我尝试检查浏览器页面时出现一个错误

任何帮助将不胜感激。提前谢谢你

【问题讨论】:

  • 是的,但是我还没有构建自定义 websockets。它在频道包中。我已经从问题中删除了 websockets.py。因为它只是显示在终端中。查看问题中的屏幕截图
  • 请不要将错误发布为截图。您可以而且应该从终端复制粘贴。
  • @AKX,我会上传
  • 欢迎来到 SO @developer !如果您能以某种方式生成minimal reproducible example,它也可能会有所帮助
  • @AjayLingayat,我上传了但我认为这是默认下载的频道。

标签: python python-3.x django django-rest-framework channel


【解决方案1】:

只要安装这个版本

pip install channels==2.4.0 

【讨论】:

    【解决方案2】:

    我自己也遇到了。使用 Channels 3.x,“消费者现在有一个 as_asgi() 类方法,您需要在设置路由时调用”

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

    https://channels.readthedocs.io/en/stable/releases/3.0.0.html#update-to-asgi-3

    【讨论】:

    • 现在是说.ValueError("No route found for path %r." % path) ValueError: No route found for path 'public_chat/1/'. WebSocket DISCONNECT /public_chat/1/ [127.0.0.1:58739]。我已经更新了我的问题(上传了我的 routing.py)
    • 你可能需要 path 而不是 re_path
    • 我改变了它,现在我得到了 1channels.exceptions.InvalidChannelLayerError: Cannot import BACKEND 'channels_redis.core.RedisChannelLayer' 为 default1 指定。更新问题(添加 settings.py)
    【解决方案3】:

    我们需要查看实例化 AsyncWebsocketConsumer 的代码来确认,但看起来它正在用一些参数实例化。

    基类AsyncConsumer 不接受__init()__ 中的附加参数,实际上它甚至没有实现__init__()。相反,它默认为object.__init__(),这就是回溯提到object.__init()__的原因。

    鉴于基类不接受任何构造参数,您无需将任何内容传递给它们的 __init__() 方法。

    所以,不要使用参数创建AsyncWebsocketConsumer,问题应该会消失。

    【讨论】:

    • 但是,我应该删除什么?
    • 当我删除 super().全线。它给了我 TypeError: PublicChatConsumer() 没有参数 WebSocket DISCONNECT /public_chat/1/ [127.0.0.1:51881]
    • 这听起来像是一个不相关的问题,现在可能已经暴露了,因为这个特定问题已得到解决。发布创建AsyncWebsocketConsumer 对象的代码。
    • 我正在上传完整的 websocets.py 文件
    • 我已经上传了
    猜你喜欢
    • 2019-12-31
    • 2020-01-25
    • 1970-01-01
    • 2020-11-14
    • 2021-12-19
    • 2021-01-06
    • 1970-01-01
    • 2021-09-15
    • 1970-01-01
    相关资源
    最近更新 更多