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()一样