Django通道-不断从服务器向客户端发送数据
请看看这个 如您所见,某种类型的Django通道-不断从服务器向客户端发送数据,django,websocket,django-channels,channels,Django,Websocket,Django Channels,Channels,请看看这个 如您所见,某种类型的事件不断地被发送到客户端。我想使用Django频道,在consumers.py内模拟这一点。以下是我所拥有的内容的简化版本: class ChatConsumer(AsyncConsumer): async def ws_connect(self, event): self.send = get_db_object() .... await self.send({ "type":
事件不断地被发送到客户端。我想使用Django频道
,在consumers.py
内模拟这一点。以下是我所拥有的内容的简化版本:
class ChatConsumer(AsyncConsumer):
async def ws_connect(self, event):
self.send = get_db_object()
....
await self.send({
"type": "websocket.accept"
})
# I need to CONSTANTLY receive & send data
async def ws_receive(self, event):
obj = ...# query DB and get the newest object
json_obj = {
'field_1': obj.field_1,
'field_2': obj.field_2,
}
await self.send({
"type": "websocket.send",
"text": json.dumps(json_obj)
})
@database_sync_to_async
def get_db_object(self, **kwargs):
return Some_Model.objects.get(**kwargs)[0]
在这里,我希望我的Django后端不断:
查询数据库
从数据库接收obj
将接收到的obj作为事件发送到前端websocket
我怎样才能做到这一点?重要的是,我需要不断地向客户发送数据
互联网上的大多数Django频道资源只包括聊天应用程序,而聊天应用程序不一定总是向客户端发送数据。我找不到任何执行此任务的工作代码
请不要再推荐redis或Channel文档。。。或者一些缺乏良好文档的随机第三方库。。。。它很容易推荐,但很难实现。例如,我发现有人推荐Snorky,但它确实缺乏关于如何实现它的文档
然而,如果有一个网站专门做这项工作,我可能会看看它,即使它不使用Django频道
谢谢大家! 我找到了解决办法。因为我注意到这篇文章的浏览量在相对较短的时间内上升了很多,我相信很多人都在想同样的事情,所以我将在这里发布
consumers.py
import asyncio
from channels.consumer import AsyncConsumer
class ChatConsumer(AsyncConsumer):
async def websocket_connect(self, event):
print("connected", event)
await self.send({
"type": "websocket.accept"
})
while True:
await asyncio.sleep(2)
obj = # do_something (Ex: constantly query DB...)
await self.send({
'type': 'websocket.send',
'text': # obj,
})
async def websocket_receive(self, event):
print("receive", event)
async def websocket_disconnect(self, event):
print("disconnected", event)
<script>
var loc = window.location;
var wsStart = 'ws://';
if (loc.protocol == 'https:') {
wsStart = 'wss://'
}
var endpoint = wsStart + loc.host + loc.pathname;
var socket = new WebSocket(endpoint);
socket.onmessage = function(e){
console.log("message", e);
};
socket.onopen = function(e){
console.log("open", e);
};
socket.onerror = function(e){
console.log("error", e)
};
socket.onclose = function(e){
console.log("close", e)
};
</script>
jQuery
import asyncio
from channels.consumer import AsyncConsumer
class ChatConsumer(AsyncConsumer):
async def websocket_connect(self, event):
print("connected", event)
await self.send({
"type": "websocket.accept"
})
while True:
await asyncio.sleep(2)
obj = # do_something (Ex: constantly query DB...)
await self.send({
'type': 'websocket.send',
'text': # obj,
})
async def websocket_receive(self, event):
print("receive", event)
async def websocket_disconnect(self, event):
print("disconnected", event)
<script>
var loc = window.location;
var wsStart = 'ws://';
if (loc.protocol == 'https:') {
wsStart = 'wss://'
}
var endpoint = wsStart + loc.host + loc.pathname;
var socket = new WebSocket(endpoint);
socket.onmessage = function(e){
console.log("message", e);
};
socket.onopen = function(e){
console.log("open", e);
};
socket.onerror = function(e){
console.log("error", e)
};
socket.onclose = function(e){
console.log("close", e)
};
</script>
var loc=窗口位置;
var wsStart='ws://';
如果(loc.protocol==“https:”){
wsStart='wss://'
}
var endpoint=wsStart+loc.host+loc.pathname;
var套接字=新的WebSocket(端点);
socket.onmessage=函数(e){
控制台日志(“消息”,e);
};
socket.onopen=函数(e){
控制台日志(“打开”,e);
};
socket.onerror=函数(e){
console.log(“错误”,e)
};
socket.onclose=函数(e){
控制台日志(“关闭”,e)
};
您只需修改并发送obj即可。您可以根据需要扩展此函数。所以,现在我感兴趣的是在我的PostgreSQL中获取最新插入的行,并将该行注入到我的websocket中。我可以按照wait asyncio.sleep(2)
的指定,每2秒查询一次数据库,并将其插入前端套接字
希望有帮助。使用channels==1.*和Django==1.*您可以使用线程模块,例如:
#Some view.py
导入线程
导入时间
类发布服务器(threading.Thread):
def u u初始(自我,回复通道,频率=0.5):
超级(出版者,自我)。\uuuu init\uuuuu()
self.\u running=True
自应答信道=应答信道
自发布间隔=1.0/频率
def运行(自):
当self.\u运行时:
self._reply_channel.send({'text':'some data'))
睡眠时间(自我发布时间间隔)
def停止(自):
self.\u running=False
出版商={}
def ws_connect(消息):
message.reply\u channel.send({'accept':True})
publisher=publisher(回复频道=message.reply频道)
publisher.start()
发布者[message.reply\u channel]=发布者
def ws_断开连接(消息):
publisher=publisher[消息.回复\u频道]
publisher.stop()
del发布者[消息.回复频道]
即使用户断开连接,循环也不会退出。在断开连接处理程序中设置一个标志,以停止循环并在带有asyncio的create_任务的函数中运行循环。我相信通道最终会杀死它,但这更像是一个错误处理程序。@Eric你能用通道1帮我做同样的事情吗?@kagronick是对的,这里面临一些问题,当它循环时,接收/断开连接不起作用,您能告诉我如何实现这一点吗?@AjayKumar使用asyncio的create\u task
启动循环的异步函数。当disconnect
触发时,将标志设置为true,并让任务退出循环。@kagronick感谢您的回复,我正在处理它,请您用一段代码解释一下,以便更清楚。提前感谢。在删除发布服务器[消息.回复频道]之前,您必须等待线程完成。就像使用thread.join()一样