Django - Websocket 网站实时线上人数

这次要藉由websocket做出网站实时的线上人数,关于django的websocket设定就不赘述了,网路上已经有相当多的资源,就写一些重点当笔记 ~

一、template

一开始最重要的就是要了解WebSocket支援的四个讯息:onopen,onmessage,onclose和onerror,然后根据你的需求去调用:

onopen:当浏览器跟websocket连线成功就可以在console看到"open"讯息,反之,连线失败则适用于onerror。
http://img2.58codes.com/2024/20129725mlR0omDLpo.pngonmessage:接收处理后端传来的资料,在这个案例指的是实时的线上人数,如上图所示目前上线人数为2人{'message':2}。
<body>    <h1 id="app">{{ text }}</h1>    <script>        var socket = new WebSocket('ws://' + window.location.host + '/ws/online_number/');        socket.onopen = function(e){              console.log ("open", e);            }        socket.onerror = function(e){          console.log ("error", e)        }        socket.onmessage = function(e){            var data = JSON.parse(e.data);            var message = data['message'];            console.log("message",e);            document.querySelector('#app').innerText = message;        }    </script></body>

二、consumers.py

我的想法很简单,只要使用者一进入网站就都放在同一个group里面,如下图的灰底部分,反之使用者一离开网站,他的资料就不会再存在于redis,然后只要再去抓取redis里的数目就会知道实时的人数了,
http://img2.58codes.com/2024/20129725SXJArpMWf0.png

那要怎么实时的在网站显示线上使用人数呢?这边有个重点就是channel_layer.group_send,首先要知道传送到哪个group(这边room_group_name是users),再来就是要传送到前端的资料(这边一定要写成字典的形式),type为指定讯息处理的函式(number),这边就是处理成传个json,message为从redis得出的人数。

用redis_connect.zcard得出在group里的数量即代表线上人数。

小结:connect跟disconnect时都要做差不多的操作来反映出实时的人数。

class NumberOfOnline(AsyncWebsocketConsumer):    db = Redis(host='127.0.0.1', port=8000, db=0)    async def connect(self):        await self.accept()        self.room_group_name = 'users'        await self.channel_layer.group_add(self.room_group_name, self.channel_name)        redis_connect = get_redis_connection('default')        online_number = str(redis_connect.zcard("asgi:group:users"))        print('线上人数', online_number)        await self.channel_layer.group_send(self.room_group_name,{'type':'number', 'message':online_number})    async def disconnect(self, close_code):        await self.channel_layer.group_discard('users', self.channel_name)        user = self.scope['user']        redis_connect = get_redis_connection('default')        online_number = str(redis_connect.zcard("asgi:group:users"))        print('线上人数', online_number)        await self.channel_layer.group_send(self.room_group_name,{'type':'number', 'message':online_number})    async def number(self, event):        message = event['message']        await self.send(text_data=json.dumps({            'message': message        }))

到目前为止只在本机测试,之后部署的话要开始研究asgi server的部分,django目前有提供daphne、Hypercorn、Uvicorn。可能会先试试daphne,但官方文件提供的资讯就只有下图这样:
http://img2.58codes.com/2024/20129725fmvYW2bYMp.png
感觉会遇到的坑不少...总之就先来try看看吧 ~


关于作者: 网站小编

码农网专注IT技术教程资源分享平台,学习资源下载网站,58码农网包含计算机技术、网站程序源码下载、编程技术论坛、互联网资源下载等产品服务,提供原创、优质、完整内容的专业码农交流分享平台。

热门文章