Django Channels WebSocket 参数
Django Channels WebSocket argument
我正在尝试 Django 实例,第 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.py
和consumer.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()),
]
来自docs:
We call the as_asgi() classmethod when routing our consumers. This returns an ASGI wrapper application that will instantiate a new consumer instance for each connection or scope. This is similar to Django’s as_view(), which plays the same role for per-request instances of class-based views.
编辑:您正在使用异步消费者,异步消费者的方法必须是协程(使用异步和等待)
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}))
我正在尝试 Django 实例,第 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.py
和consumer.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()),
]
来自docs:
We call the as_asgi() classmethod when routing our consumers. This returns an ASGI wrapper application that will instantiate a new consumer instance for each connection or scope. This is similar to Django’s as_view(), which plays the same role for per-request instances of class-based views.
编辑:您正在使用异步消费者,异步消费者的方法必须是协程(使用异步和等待)
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}))