没有消息类型 websocket.group_send 的处理程序,如何修复?

Hat*_* Me 5 python django websocket django-channels

我从一个用户的 websocket 连接切换到聊天室,两个人可以互相连接,但是在切换时,在 receive 方法中,现在需要 group_send,之后就停止工作了,如何修复?

完整回溯

> Exception inside application: No handler for message type
> websocket.group_send   File
> "D:\Dev\Web\Chaty\lib\site-packages\channels\sessions.py", line 183,
> in __call__
>     return await self.inner(receive, self.send)   File "D:\Dev\Web\Chaty\lib\site-packages\channels\middleware.py", line 41,
> in coroutine_call
>     await inner_instance(receive, send)   File "D:\Dev\Web\Chaty\lib\site-packages\channels\consumer.py", line 59, in
> __call__
>     [receive, self.channel_receive], self.dispatch   File "D:\Dev\Web\Chaty\lib\site-packages\channels\utils.py", line 52, in
> await_many_dispatch
>     await dispatch(result)   File "D:\Dev\Web\Chaty\lib\site-packages\channels\consumer.py", line 75, in
> dispatch
>     raise ValueError("No handler for message type %s" % message["type"])   No handler for message type websocket.group_send
> WebSocket DISCONNECT /messages/dildo/ [127.0.0.1:58910]
Run Code Online (Sandbox Code Playgroud)

消费者

import asyncio
import json
from django.contrib.auth import get_user_model
from channels.consumer import AsyncConsumer
from channels.db import database_sync_to_async

from .models import Thread, ChatMessage



class ChatConsumer(AsyncConsumer):

    async def websocket_connect(self, event):
        print('Connected', event)
        other_user = self.scope['url_route']['kwargs']['username']
        me = self.scope['user']
        thread_obj = await self.get_thread(me, other_user)
        chat_room = f"thread_{thread_obj.id}"
        self.chat_room = chat_room
        await self.channel_layer.group_add(
            chat_room,
            self.channel_name
        )

        await self.send({
            'type':'websocket.accept'
        })

    async def websocket_receive(self, event):
        print('Recive', event)

        front_response = event.get('text', None)

        if front_response is not None:
            compiled_response_data = json.loads(front_response)

            if 'FormData' in compiled_response_data:
                pass
        author = str(self.scope['user'])

        Response_ = {
            'Message': compiled_response_data['FormData']['message'],
            'Author': author
        } 

        new_event = {
            'type':'websocket.send',
            'text': json.dumps(Response_)

        }
        print(new_event)
        await self.channel_layer.group_send(
            self.chat_room,
            new_event
        )
    async def websocket_disconnect(self, event):
        print('Disconnected', event)

    @database_sync_to_async
    def get_thread(self, user, other_username):
        return Thread.objects.get_or_new(user, other_username)[0]
Run Code Online (Sandbox Code Playgroud)

我的 html 模板

{% extends "base.html" %}

{% block content %}
<h3>Thread for {% if user != object.first %}{{ object.first }}{% else %}{{ object.second }}{% endif %}</h3>
<ul id='chat-items'>
{% for chat in object.chatmessage_set.all %}

<li>{{ chat.message }} via {{ chat.user }}</li>

{% endfor %}
</ul>

<form id='form' method='POST'> {% csrf_token %}
{{form }}
<input type="text" name='porn'>
<input type="text" name='pov'>
<button type='submit' class='btn btn-primary'>Submit</button>
</form>

{% endblock %}

{% block script %}

<script>
    const from_user = '{{ object.first }}',
        to_user = '{{ object.second }}';
// websocket scripts
    let loc = window.location,
        path_first_part = 'ws://',
        path_second_part = loc.host + loc.pathname,
        endpoint = '',
        FormItself = $('#form'),
        FormData = $('#form input'),
        DataHolder = {},
        ChatItself = $("#chat-items");
    if (loc.protocol == 'https:'){
        path_first_part = 'wss://'
    }else{
        path_first_part = 'ws://'
    }
    endpoint = path_first_part + path_second_part
    let socket = new WebSocket(endpoint);

    socket.onmessage = function(e){
        console.log('Message', e);
        let parset_data = JSON.parse(e.data),
            Chat_MSG =  parset_data.Message,
            Chat_AUTHOR =  parset_data.Author;

        ChatItself.append('<li>' + Chat_MSG + ' <= via => ' + Chat_AUTHOR + '</li>');

    };
    socket.onopen = function(e){
        console.log('Open', e)
        FormItself.submit(function(event){
            event.preventDefault();
            DataHolder['FormData'] = {};
            FormData.each(function(key, value){
                DataHolder['FormData'][value.name] = value.value;
                value.value = '';
            })
            socket.send(JSON.stringify(DataHolder));
        })
        console.log(DataHolder)
    };
    socket.onerror = function(e){
        console.log('Error', e)
    };
    socket.onclose = function(e){
        console.log('Close', e)
    };

</script>
{% endblock %}
Run Code Online (Sandbox Code Playgroud)

看起来你的帖子主要是代码;请添加更多详细信息。

Hat*_* Me 7

老兄,我\xe2\x80\x99m很高兴帮助你,我自己就遇到过一个,你一创建组,那么你需要向该组发送消息,即在type: \'websocket.send\'\n websocket_receive中你需要放一个回调函数,您已经可以使用向 websocket 发送消息了。

\n\n
new_event = {\n            \'type\':\'chat_message\',\n            \'text\': json.dumps(Response_)\n\n        }\n
Run Code Online (Sandbox Code Playgroud)\n\n

接下来创建 chat_message 回调函数

\n\n
async def chat_message(self, event):\n    print(\'\\n\',event)\n    front_response = event.get(\'text\', None)\n    if front_response is not None:\n        compiled_response_data = json.loads(front_response)\n    Response_ = {\n        \'Message\': compiled_response_data[\'Message\'],\n        \'Author\': compiled_response_data[\'Author\']\n    } \n\n    # Send message to WebSocket\n    await self.send({\n        \'type\':\'websocket.send\',\n        \'text\': json.dumps(Response_)\n    })\n
Run Code Online (Sandbox Code Playgroud)\n\n

所以最终你的消费者将看起来像这样。

\n\n
import asyncio\nimport json\nfrom django.contrib.auth import get_user_model\nfrom channels.consumer import AsyncConsumer\nfrom channels.db import database_sync_to_async\n\nfrom .models import Thread, ChatMessage\n\n\n\nclass ChatConsumer(AsyncConsumer):\n\n    async def websocket_connect(self, event):\n        print(\'Connected\', event)\n        other_user = self.scope[\'url_route\'][\'kwargs\'][\'username\']\n        me = self.scope[\'user\']\n        thread_obj = await self.get_thread(me, other_user)\n        chat_room = f"thread_{thread_obj.id}"\n        self.chat_room = chat_room\n        await self.channel_layer.group_add(\n            chat_room,\n            self.channel_name\n        )\n\n        await self.send({\n            \'type\':\'websocket.accept\'\n        })\n\n    async def websocket_receive(self, event):\n        print(\'Recive\', event)\n\n        front_response = event.get(\'text\', None)\n\n        if front_response is not None:\n            compiled_response_data = json.loads(front_response)\n\n            if \'FormData\' in compiled_response_data:\n                pass\n        author = str(self.scope[\'user\'])\n\n        Response_ = {\n            \'Message\': compiled_response_data[\'FormData\'][\'message\'],\n            \'Author\': author\n        } \n\n        new_event = {\n            \'type\':\'chat_message\',\n            \'text\': json.dumps(Response_)\n\n        }\n        await self.channel_layer.group_send(\n            self.chat_room,\n            new_event\n        )\n    async def websocket_disconnect(self, event):\n        print(\'Disconnected\', event)\n\n    # Receive message from room group\n    async def chat_message(self, event):\n        print(\'\\n\',event)\n        front_response = event.get(\'text\', None)\n        if front_response is not None:\n            compiled_response_data = json.loads(front_response)\n        author = str(self.scope[\'user\'])\n        Response_ = {\n            \'Message\': compiled_response_data[\'Message\'],\n            \'Author\': author\n        } \n        message = event[\'text\']\n\n        # Send message to WebSocket\n\n        await self.send({\n            \'type\':\'websocket.send\',\n            \'text\': json.dumps(Response_)\n        })\n\n    @database_sync_to_async\n    def get_thread(self, user, other_username):\n        return Thread.objects.get_or_new(user, other_username)[0]\n\n    #saving to db\n    @database_sync_to_async\n    def create_chat_message(self, author, msg):\n        thread_obj = self.thread_obj\n        return ChatMessage.objects.create(thread=thread_obj, user=author, message=msg)\n
Run Code Online (Sandbox Code Playgroud)\n