Django Channels-不断从服务器向客户端发送数据

Eri*_*Kim 6 django websocket channels django-channels

请看这个例子

如您所见,某种形式的event内容不断发送给客户端。我想模仿Django-Channels里面使用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]
Run Code Online (Sandbox Code Playgroud)

在这里,我希望我的Django后端能够不断运行:

  1. 查询数据库

  2. 从数据库接收obj

  3. 将收到的obj发送给前端Websocket event

我该如何实现?重要的是,我需要不变地将数据发送到客户端。

Django-Channels互联网上的大多数资源仅包含聊天应用程序,而不必经常将数据发送到客户端。我找不到能完成此工作的任何工作代码。

请不要再提出关于Redis或渠道文档的建议...或者缺少一些缺少良好文档的随机第3方库...。推荐起来很容易,但是很难实现。例如,我发现有人推荐Snorky,但是它确实缺少有关如何实现它的文档。

但是,如果有一个专门负责此工作的网站,即使它不使用Django-Channels,我也可能会看一下。

谢谢!

Eri*_*Kim 5

我找到了解决方案。由于我注意到这篇文章的观看次数在相对较短的时间内就上升了很多,因此我相信很多人都在想同样的事情,所以我将其发布在这里。

users.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)
Run Code Online (Sandbox Code Playgroud)

jQuery的

<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>
Run Code Online (Sandbox Code Playgroud)

您只需要修改obj并发送即可。您可以根据需要扩展此功能。因此,现在我有兴趣在PostgreSQL中获取最新插入的行,并将该行注入到我的websocket中。我可以按所指定的那样每2秒查询一次数据库await asyncio.sleep(2),并将其注入到前端套接字中。

希望能帮助到你。

  • 即使用户断开连接,循环也不会退出。在断开连接处理程序中设置一个标志,以停止循环并在带有asyncio的create_task的函数中运行循环。我相信Channels最终会杀死它,但这更多是一个错误处理程序。 (4认同)