Django Channels - constantly send data to client from server

房东的猫 提交于 2019-11-30 12:19:49

问题


Please take a look at this example.

As you can see, some sort of event is constantly being sent to the client. I want to imitate this using Django-Channels, inside consumers.py. Here's a simplified version of what I have:

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]

Here, I want my Django backend to constantly:

  1. Query DB

  2. Receive obj from DB

  3. Send the received obj to Front-End websocket as event

How can I achieve this? The important thing is that I need to CONSTANTLY send data to client.

Most of the Django-Channels resources on the internet covers only Chat Apps, which doesn't necessarily constantly send data to client. I couldn't find any working codes that does this job.

Please, no more recommendation for redis or channels documentation... or some random 3rd party libraries that lacks good documentation.... It's easy to recommend but hard to implement. For example, I found someone recommending Snorky, but it really lacks documentation on how to implement it.

However, if there's an website that specifically does this job, I might take a look at it, even if it doesn't use Django-Channels.

Thank you!


回答1:


I've found a solution. Since I noticed the view count for this post went up pretty high in a relatively short time, I believe that lots of people are wondering the same thing, so I will post it here.

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)

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>

All you need to do is just modify obj and send it. You can extend this function as much as you want. So, right now I'm interested in getting the latest inserted row in my PostgreSQL, and injecting that row into my websocket. I can query my DB every 2 seconds as it was specified by await asyncio.sleep(2), and inject it into the Front-End socket.

Hope it helps.



来源:https://stackoverflow.com/questions/51725863/django-channels-constantly-send-data-to-client-from-server

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!