django+python搭建消息推送系统

django+channels+websocket完成一个实时推送系统

前言

因公司项目需求,需要建立一个展示网站,接入两台摄像机,当摄像机的照片流传过来的时候,实时展示到网页中,所以需要做一个实时推送系统的小demo,因接触django时间不长(两周左右),也算边做边学习了,网上用channels做实时聊天系统的较多,实时推送系统的比较少。

好了,进入正题。demo采用pycharm+django开发,具体用到的库有:channels、channels_redis。关于项目建立的步骤自行百度,不多赘述,pycharm建立django项目的时候已经帮你建立好了虚拟环境,很多事情基本上不需要你做了,直接码代码就可以了!!!
(下面示例的项目名称(project:mysite,app:myapp)
在这里插入图片描述

项目配置

1、先添加相关库
工具栏File–>Settings–>Project:(mysite)–>Project Interpreter–>±->channels+channel-redis
特别注意,channels-redis版本选择2.4.2,选择3.0.1会和本地redis服务器冲突,原因不详。
在这里插入图片描述
将这两个库添加进去
2、修改项目settings
将你创建的app和channels一并添加进去
在这里插入图片描述
因为使用channels_redis,咱们就一并修改了

ASGI_APPLICATION = 'mysite.routing.application'
CHANNEL_LAYERS = {
    
    
    'default': {
    
    
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
    
    
            "hosts": [('127.0.0.1', 6379)],
        },
    },
}

3、修改路由
(也可以不做这一步,只是为了让项目路由分类更加清晰,便于后期维护)
添加app路由
在myapp的目录下创建一个urls.py文件
/myapp/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index),
]

然后在项目路由下导入你的app路由
/mysite/urls.py

from django.conf.urls import include
from django.urls import path

urlpatterns = [
    path('', include('myapp.urls')),
]

以上这一步等于直接在
/mysite/urls.py 修改

from django.urls import path
from . import views

urlpatterns = [
	path('', views.index),
]

4、添加asgi应用路由
咱们在settings已经修改了ASGI_APPLICATION = ‘mysite.routing.application’
因此在/mysite/新建一个routing.py

from channels.auth import AuthMiddlewareStack
from channels.routing import ProtocolTypeRouter, URLRouter
import myapp.routing

application = ProtocolTypeRouter({
    
    
    'websocket': AuthMiddlewareStack(
        URLRouter(
            myapp.routing.websocket_urlpatterns
        )
    ),
})

这里简单的解释一下:它使您可以根据中type存在的值将其分派到许多其他ASGI应用程序 之一scope。协议将定义其作用域包含的固定类型值,因此您可以使用它来区分传入的连接类型。
简而言之就是根据你的需求指向不同的url(连接的是你的视图函数)

接着添加应用的路由
即/myapp/routing.py

from django.urls import path
from . import consumers

websocket_urlpatterns = [
    path('image/', consumers.PushConsumer),
]

5、创建后台的推送函数
在myapp目录下创建consumers.py
/myapp/consumers.py

import json
from channels.generic.websocket import AsyncWebsocketConsumer
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layer


# 推送consumer
class PushConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.group_name = 'image'
        await self.channel_layer.group_add(
            self.group_name,
            self.channel_name
        )
        await self.accept()

    async def disconnect(self, close_code):
        await self.channel_layer.group_discard(
            self.group_name,
            self.channel_name
        )
        # print(PushConsumer.chats)

    async def push_message(self, event):
        await self.send(text_data=json.dumps({
    
    
            "message": event['message']
        }))

# 构建函数,便于外部调用
def push(username, message):
    channel_layer = get_channel_layer()
    async_to_sync(channel_layer.group_send)(
        username,
        {
    
    
            "type": "push.message",
            "message": message
        }
    )

6、不要忘了我们的视图函数view.py

from django.shortcuts import render
from .consumers import push

# Create your views here.
def index(request):
    for i in range(10):
        push('image',i)
    return render(request, 'index.html')

这里举了一个简单调用的例子
for i in range(10):
push(‘image’,i)
向image组的所有成员推送0,1、2、3…9
就是那么简单

7、在网页建立我们的websocket连接
建立一个index.html页面

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <title>接收端</title>
</head>
<body>
    <textarea id="log" cols="100" rows="20"></textarea><br>
    <script>
        const chatSocket = new WebSocket(
            'ws://'
            + window.location.host
                +'/image/'
        );

        chatSocket.onmessage = function(e) {
    
    
            const data = JSON.parse(e.data);
            document.querySelector('#log').value += (data.message + '\n');
        };
        chatSocket.onclose = function(e) {
    
    
            console.error('Chat socket closed unexpectedly');
        };

    </script>
</body>
</html>

这样就建立好websocket连接了

测试

打开本地的redis服务器,打开方法请自行百度下载并打开进行测试
就是下面这个东东
官网下载过慢,慢到让你窒息,别傻傻的等,请自行寻找国内资源。
在这里插入图片描述

如果是采用的本地测试,直接在本地打开几个网页,默认的为127.0.0.1:8000。基本效果就是没打开一个网页,上一个网页就是打印0-9的数字
在这里插入图片描述
如果是采用局域网的方法
在settings.py文件中修改

ALLOWED_HOSTS = [你本地电脑的IP地址]

这样就可以在同一局域网的另一台电脑打开网页进行测试,效果和本地测试相同。

以上,菜鸟一枚,欢迎指正,哈哈~
如果有不懂的可以多多查看官方文档:channels官方文档
相关文档

猜你喜欢

转载自blog.csdn.net/qq_41750806/article/details/106078181
今日推荐