Django 通道 2 和信号:Websocket 连接失败
Django Channels 2 and Signals: Websocket Connections failed
我正在使用通道 2 和信号来检测何时保存某种类型的模型并向所有客户端推送通知。我收到错误消息:与 'ws:/account/home' 的 WebSocket 连接失败:WebSocket 在建立连接之前关闭。我不明白我在哪里犯了错误。
非常感谢您的帮助。
在我的项目中:FUNDBOOK_V5/ROUTING.PY
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import FundBook_Core.routing
application = ProtocolTypeRouter({
# (http->django views is added by default)
'websocket': AuthMiddlewareStack(
URLRouter(
FundBook_Core.routing.websocket_urlpatterns
)
),
})
在我的应用程序中:FUNDBOOK_CORE\ROUTING.PY
from django.urls import re_path
from django.conf.urls import url
from . import consumers
websocket_urlpatterns = [
url(r'^account/home/$', consumers.NotificationConsumer),
url(r'^fund/(?P<fund>[\w-]+)/$', consumers.NotificationConsumer),
]
FUNDBOOK_CORE\CONSUMERS.PY
import json
import asyncio
from django.contrib.auth import get_user_model
from channels.generic.websocket import AsyncJsonWebsocketConsumer, AsyncConsumer
class NotificationConsumer(AsyncConsumer):
async def websocket_connect(self, event):
await self.channel_layer.group_add("task", self.channel_name)
await self.send({
"type": "websocket.accept"
})
print("Connected!", event)
async def websocket_disconnect(self, event):
await self.channel_layer.group_discard("task", self.channel_name)
print("Disconnected!", event)
async def send_message(self, event):
await self.send({
"type": "websocket.send",
'text': 'Oy, mate!'
})
SIGNALS.PY
from FundBook_Core.models import ThreadTask
from django.db.models.signals import pre_save
from django.dispatch import receiver
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
@receiver(pre_save, sender=ThreadTask)
def notify_thread_task_save(sender, **kwargs):
if "instance" in kwargs:
instance = kwargs["instance"]
# check if there is a new notification
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
"task", {"type": "send_message",
"event": "New Notification",
"username": instance.username}
)
FUNDBOOK_CORE\INIT.PY
default_app_config = "FundBook_Core.apps.FundbookCoreConfig"
FUNDBOOK_CORE\APPS.PY
from django.apps import AppConfig
class FundbookCoreConfig(AppConfig):
name = 'FundBook_Core'
def ready(self):
from . import signals
SETTINGS.PY
ALLOWED_HOSTS = ['*']
ASGI_APPLICATION = 'FundBook_v5.routing.application'
# Channels
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {"hosts": [("localhost", 6379)]},
}
}
HOME.HTML:
<script>
var loc = window.location;
var wsStart = "ws://"
if (loc.protocol === 'https:'){
wsStart = 'wss://'
}
var url = wsStart + loc.host + loc.pathname;
console.log(url)
var socket = new ReconnectingWebSocket(url);
socket.onmessage = function(e) {
console.log("message", e)
const data = JSON.parse(e.data);
document.querySelector('#notifylist').value += (data.message + '\n');
}
socket.onopen = function(e) {
console.log("open", e)
}
socket.onerror = function(e) {
console.log("error", e)
console.error('Notification socket closed unexpectedly')
}
socket.onclose = function(e) {
console.log("close", e)
}
</script>
其实我有两个问题:
第一个:ERR_CONNECTION_RESET 问题是由于防火墙阻止 websocket 连接或未配置为处理 websocket 连接而引起的。
第二个错误:错误 - 服务器 - 应用程序内部异常:多个异常:[Errno 10061] Connect call failed ('::1', 6379), [Errno 10061] Connect call failed ('127. 0.0.1', 6379)来自 redit 数据库:见
在我解决了这些问题之后,一切正常。对于那些需要代码的人:
APP.初始化
default_app_config = "your_application.apps.FundbookCoreConfig"
APP.APPS
from django.apps import AppConfig
class your_appConfig(AppConfig):
name = 'your_app'
def ready(self):
from . import signals
PROJECT.SETTINGS
ASGI_APPLICATION = 'your_project.routing.application'
# Channels
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {"hosts": [("localhost", 6379)]},
}
}
APP.SIGNALS
from django.db.models.signals import pre_save
from django.dispatch import receiver
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from.models import ThreadTask
@receiver(pre_save, sender=ThreadTask)
def notify_thread_task_save(sender, **kwargs):
if "instance" in kwargs:
instance = kwargs["instance"]
# check if there is a new notification
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
"task", {"type": "user_notification",
"event": "New Notification",
"notification": instance.text}
)
PROJECT.ROUTING
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator, OriginValidator
import your_app.routing
application = ProtocolTypeRouter({
# (http->django views is added by default)
'websocket': AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
FundBook_Core.routing.websocket_urlpatterns
)
)
),
})
APP.ROUTING
from django.conf.urls import url
from . import consumers
websocket_urlpatterns = [
url(r'^account/home', consumers.NotificationConsumer),
url(r'^fund/(?P<fund>[\w-]+)', consumers.NotificationConsumer),
]
APP.CONSUMERS
from channels.generic.websocket import AsyncJsonWebsocketConsumer
class NotificationConsumer(AsyncJsonWebsocketConsumer):
async def connect(self):
await self.accept()
await self.channel_layer.group_add("task", self.channel_name)
print(f"Added {self.channel_name} channel to task")
async def disconnect(self, close_code):
await self.channel_layer.group_discard("task", self.channel_name)
print(f"Removed {self.channel_name} channel to task")
async def user_notification(self, event):
await self.send_json(event)
print(f"Got message {event} at {self.channel_name}")
在你的html
<!-- Plugin JavaScript -->
<script src="{% static "FundBook_Core/js/reconnecting-websocket.js" %}"></script>
<script>
var loc = window.location;
var wsStart = "ws://"
if (loc.protocol === 'https:'){
wsStart = 'wss://'
}
var url = wsStart + loc.host + loc.pathname;
console.log(url)
var socket = new ReconnectingWebSocket(url);
const tt = document.querySelector('#task_text');
socket.onmessage = function(e) {
console.log("message", e)
const data = JSON.parse(e.data);
console.log("parse", data)
console.log("notification", data.notification)
if(data.event == "New Notification"){
var el = document.createElement("li");
el.innerHTML = data.notification;
tt.appendChild(el);
}
}
socket.onopen = function(e) {
console.log("open", e)
}
socket.onerror = function(e) {
console.log("error", e);
console.error('Notification socket closed unexpectedly')
}
socket.onclose = function(e) {
console.log("close", e)
}
</script>
我正在使用通道 2 和信号来检测何时保存某种类型的模型并向所有客户端推送通知。我收到错误消息:与 'ws:/account/home' 的 WebSocket 连接失败:WebSocket 在建立连接之前关闭。我不明白我在哪里犯了错误。 非常感谢您的帮助。
在我的项目中:FUNDBOOK_V5/ROUTING.PY
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import FundBook_Core.routing
application = ProtocolTypeRouter({
# (http->django views is added by default)
'websocket': AuthMiddlewareStack(
URLRouter(
FundBook_Core.routing.websocket_urlpatterns
)
),
})
在我的应用程序中:FUNDBOOK_CORE\ROUTING.PY
from django.urls import re_path
from django.conf.urls import url
from . import consumers
websocket_urlpatterns = [
url(r'^account/home/$', consumers.NotificationConsumer),
url(r'^fund/(?P<fund>[\w-]+)/$', consumers.NotificationConsumer),
]
FUNDBOOK_CORE\CONSUMERS.PY
import json
import asyncio
from django.contrib.auth import get_user_model
from channels.generic.websocket import AsyncJsonWebsocketConsumer, AsyncConsumer
class NotificationConsumer(AsyncConsumer):
async def websocket_connect(self, event):
await self.channel_layer.group_add("task", self.channel_name)
await self.send({
"type": "websocket.accept"
})
print("Connected!", event)
async def websocket_disconnect(self, event):
await self.channel_layer.group_discard("task", self.channel_name)
print("Disconnected!", event)
async def send_message(self, event):
await self.send({
"type": "websocket.send",
'text': 'Oy, mate!'
})
SIGNALS.PY
from FundBook_Core.models import ThreadTask
from django.db.models.signals import pre_save
from django.dispatch import receiver
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
@receiver(pre_save, sender=ThreadTask)
def notify_thread_task_save(sender, **kwargs):
if "instance" in kwargs:
instance = kwargs["instance"]
# check if there is a new notification
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
"task", {"type": "send_message",
"event": "New Notification",
"username": instance.username}
)
FUNDBOOK_CORE\INIT.PY
default_app_config = "FundBook_Core.apps.FundbookCoreConfig"
FUNDBOOK_CORE\APPS.PY
from django.apps import AppConfig
class FundbookCoreConfig(AppConfig):
name = 'FundBook_Core'
def ready(self):
from . import signals
SETTINGS.PY
ALLOWED_HOSTS = ['*']
ASGI_APPLICATION = 'FundBook_v5.routing.application'
# Channels
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {"hosts": [("localhost", 6379)]},
}
}
HOME.HTML:
<script>
var loc = window.location;
var wsStart = "ws://"
if (loc.protocol === 'https:'){
wsStart = 'wss://'
}
var url = wsStart + loc.host + loc.pathname;
console.log(url)
var socket = new ReconnectingWebSocket(url);
socket.onmessage = function(e) {
console.log("message", e)
const data = JSON.parse(e.data);
document.querySelector('#notifylist').value += (data.message + '\n');
}
socket.onopen = function(e) {
console.log("open", e)
}
socket.onerror = function(e) {
console.log("error", e)
console.error('Notification socket closed unexpectedly')
}
socket.onclose = function(e) {
console.log("close", e)
}
</script>
其实我有两个问题:
第一个:ERR_CONNECTION_RESET 问题是由于防火墙阻止 websocket 连接或未配置为处理 websocket 连接而引起的。
第二个错误:错误 - 服务器 - 应用程序内部异常:多个异常:[Errno 10061] Connect call failed ('::1', 6379), [Errno 10061] Connect call failed ('127. 0.0.1', 6379)来自 redit 数据库:见
在我解决了这些问题之后,一切正常。对于那些需要代码的人:
APP.初始化
default_app_config = "your_application.apps.FundbookCoreConfig"
APP.APPS
from django.apps import AppConfig
class your_appConfig(AppConfig):
name = 'your_app'
def ready(self):
from . import signals
PROJECT.SETTINGS
ASGI_APPLICATION = 'your_project.routing.application'
# Channels
CHANNEL_LAYERS = {
"default": {
"BACKEND": "channels_redis.core.RedisChannelLayer",
"CONFIG": {"hosts": [("localhost", 6379)]},
}
}
APP.SIGNALS
from django.db.models.signals import pre_save
from django.dispatch import receiver
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer
from.models import ThreadTask
@receiver(pre_save, sender=ThreadTask)
def notify_thread_task_save(sender, **kwargs):
if "instance" in kwargs:
instance = kwargs["instance"]
# check if there is a new notification
channel_layer = get_channel_layer()
async_to_sync(channel_layer.group_send)(
"task", {"type": "user_notification",
"event": "New Notification",
"notification": instance.text}
)
PROJECT.ROUTING
from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
from channels.security.websocket import AllowedHostsOriginValidator, OriginValidator
import your_app.routing
application = ProtocolTypeRouter({
# (http->django views is added by default)
'websocket': AllowedHostsOriginValidator(
AuthMiddlewareStack(
URLRouter(
FundBook_Core.routing.websocket_urlpatterns
)
)
),
})
APP.ROUTING
from django.conf.urls import url
from . import consumers
websocket_urlpatterns = [
url(r'^account/home', consumers.NotificationConsumer),
url(r'^fund/(?P<fund>[\w-]+)', consumers.NotificationConsumer),
]
APP.CONSUMERS
from channels.generic.websocket import AsyncJsonWebsocketConsumer
class NotificationConsumer(AsyncJsonWebsocketConsumer):
async def connect(self):
await self.accept()
await self.channel_layer.group_add("task", self.channel_name)
print(f"Added {self.channel_name} channel to task")
async def disconnect(self, close_code):
await self.channel_layer.group_discard("task", self.channel_name)
print(f"Removed {self.channel_name} channel to task")
async def user_notification(self, event):
await self.send_json(event)
print(f"Got message {event} at {self.channel_name}")
在你的html
<!-- Plugin JavaScript -->
<script src="{% static "FundBook_Core/js/reconnecting-websocket.js" %}"></script>
<script>
var loc = window.location;
var wsStart = "ws://"
if (loc.protocol === 'https:'){
wsStart = 'wss://'
}
var url = wsStart + loc.host + loc.pathname;
console.log(url)
var socket = new ReconnectingWebSocket(url);
const tt = document.querySelector('#task_text');
socket.onmessage = function(e) {
console.log("message", e)
const data = JSON.parse(e.data);
console.log("parse", data)
console.log("notification", data.notification)
if(data.event == "New Notification"){
var el = document.createElement("li");
el.innerHTML = data.notification;
tt.appendChild(el);
}
}
socket.onopen = function(e) {
console.log("open", e)
}
socket.onerror = function(e) {
console.log("error", e);
console.error('Notification socket closed unexpectedly')
}
socket.onclose = function(e) {
console.log("close", e)
}
</script>