WebSocket 握手期间的 Django 通道错误:意外的响应代码:500

Django channels Error during WebSocket handshake: Unexpected response code: 500

我使用以下教程 (https://channels.readthedocs.io/en/latest/tutorial/part_1.html) 了解 Django 通道以换出当前项目中的 ajax 短轮询。

我已将所有内容插入到我的项目中,它应该 运行 没问题,除非 websocket 断开连接。浏览器显示 WebSocket connection to 'ws://localhost:8001/ws/members/vote/2/' failed: Error during WebSocket handshake: Unexpected response code: 500.

终端输出:

2019-12-02 19:44:23,543 ERROR    Exception inside application: 'room_name'
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/channels/sessions.py", line 183, in __call__
    return await self.inner(receive, self.send)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/channels/middleware.py", line 41, in coroutine_call
    await inner_instance(receive, send)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/channels/consumer.py", line 59, in __call__
    [receive, self.channel_receive], self.dispatch
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/channels/utils.py", line 51, in await_many_dispatch
    await dispatch(result)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/asgiref/sync.py", line 244, in __call__
    return await asyncio.wait_for(future, timeout=None)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/asyncio/tasks.py", line 339, in wait_for
    return (yield from fut)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/concurrent/futures/thread.py", line 56, in run
    result = self.fn(*self.args, **self.kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/channels/db.py", line 14, in thread_handler
    return super().thread_handler(loop, *args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/asgiref/sync.py", line 277, in thread_handler
    return func(*args, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/channels/consumer.py", line 105, in dispatch
    handler(message)
  File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/channels/generic/websocket.py", line 39, in websocket_connect
    self.connect()
  File "./vote/consumers.py", line 10, in connect
    self.room_name = self.scope['url_route']['kwargs']['room_name']
  'room_name'
127.0.0.1:54775 - - [02/Dec/2019:19:44:23] "WSDISCONNECT /ws/members/vote/2/" - -

这是我的代码片段

Vote.html

<script>
    var questionID = {{ question_id_json }};

    var chatSocket = new WebSocket(
        'ws://' + window.location.host +
        '/ws/members/vote/' + questionID + '/');

    chatSocket.onmessage = function(e) {
        var data = JSON.parse(e.data);
        console.log(data);
        var vote = data['vote'];
        var allvotes = data['allvotes'];
        console.log(allvotes);
        drawChart(allvotes);
    };

    chatSocket.onclose = function(e) {
        console.error('Chat socket closed unexpectedly');
    };

    document.querySelector('#chat-message-submit').onclick = function(e) {
        var voteInputDom = document.querySelector('#vote-input');
        var vote = voteInputDom.value;
        chatSocket.send(JSON.stringify({
            'vote': vote
        }));
    };
    </script>

Vote/routing.py

from django.urls import re_path
from . import consumers


websocket_urlpatterns = [
    re_path(r'^ws/members/vote/(?P<question_id>\d+)/$', consumers.ChatConsumer),
]

Vote/consumers.py

from asgiref.sync import async_to_sync
from channels.generic.websocket import WebsocketConsumer
from django.db.models import Count
from .models import Vote
import json


class ChatConsumer(WebsocketConsumer):
    def connect(self):
        self.room_name = self.scope['url_route']['kwargs']['room_name']
        self.room_group_name = 'vote_%s' % self.room_name

        # Join room group
        async_to_sync(self.channel_layer.group_add)(
            self.room_group_name,
            self.channel_name
        )

        self.accept()

    def disconnect(self, close_code):
        # Leave room group
        async_to_sync(self.channel_layer.group_discard)(
            self.room_group_name,
            self.channel_name
        )

    # Receive message from WebSocket
    def receive(self, text_data):
        text_data_json = json.loads(text_data)
        vote = text_data_json['vote']
        print(vote)
        save_question = Vote(value=vote)
        save_question.save()
        votes = Vote.objects.values('value').order_by('value').annotate(count=Count('value'))
        allvotes = []
        for x in range(1, 10):
            trigger = False
            for vote_item in votes:
                if int(vote_item['value']) == x:
                    allvotes.append(vote_item['count'])
                    trigger = True
                    break
            if trigger is False:
                allvotes.append(0)


        # Send message to room group
        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name,
            {
                'type': 'chat_message',
                'vote': vote,
                'allvotes': allvotes
            }
        )

    # Receive message from room group
    def chat_message(self, event):
        vote = event['vote']
        allvotes = event['allvotes']
        # Send message to WebSocket
        self.send(text_data=json.dumps({
            'vote': vote,
            'allvotes': allvotes,
        }))

我在Setting.py

中设置了redis
ASGI_APPLICATION = "pullingapp.routing.application"

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

只是将我的评论表述为答案。堆栈跟踪显示您正在尝试获取不存在的 url kwarg room_name。从你的 vote/routing.py 中,只有 question_id url kwarg 存在,所以这可能是你想要得到的