Django3框架-(3)-[使用websocket]:使用channels实现websocket功能;简化的配置和实际使用方式

概述:

对于Django使用channels实现websocket的功能,之前就写了几篇博文了。随着在项目的使用和实际维护来说,重新设置了相关处理方法。

一般来说,前后端都只维护一个全局的连接,通过携带数据来判断具体的操作,大致的业务逻辑(非群聊功能):

1、前端主动发起连接,发送了数据给后端,后端获取到数据后,解析出前端需要的是啥数据,查询出数据,返回给前端。(一次请求一次返回了)

2、部分数据变化了,后端需要主动告知前端,让前端重新查询对应的数据。(实时更新数据)

一、依赖

python=3.9.0

包:

pip install channels==3.0.0
pip install daphne==3.0.2
pip install redis==4.6.0
pip install channels-redis=3.1.0

django-cors-headers==3.5.0

项目结构:

项目名

  • apps

    • user

    • websocket

      • routings.py

      • consumers.py

      • update.py

      • send_date.py

      • __init__.py

  • 项目名

    • settings.py

    • asgi.py

    • urls.py

    • wsgi.py

    • __init__.py

  • manage.py

二、settings.py设置

#注册channels
INSTALLED_APPS = [...'channels',  # django通过其实现websocket
]WSGI_APPLICATION = 'HeartFailure.wsgi.application'#channels使用需要添加ASGI_APPLICATION
ASGI_APPLICATION = 'HeartFailure.asgi.application'#使用channel_layers需要配置通道
CHANNEL_LAYERS = {"default": {#1、使用内存作为通道(开发使用)"BACKEND": "channels.layers.InMemoryChannelLayer",#2、使用redis(上线使用)# 'BACKEND': 'channels.layers.RedisChannelLayer',# 'CONFIG': {#     'hosts': [('localhost', 6379)],# },}
}#####1、 cors资源跨域共享配置
CORS_ORIGIN_ALLOW_ALL = True
CORS_ALLOW_METHODS = ('DELETE','GET','OPTIONS','PATCH','POST','PUT','VIEW',
)CORS_ALLOW_HEADERS = ('XMLHttpRequest','X_FILENAME','accept-encoding','authorization','content-type','dnt','origin','user-agent','x-csrftoken','x-requested-with','Pragma','token' #请求头允许自定义的字符串
)

三、创建websocket包

概述:将所有的wesocket相关的请求都放到一个包,集中管理。

 

websocket包下创建:

  • routings.py

    • 存放websocket请求相关的路由信息

  • consumers.py

    • 存放websocket请求处理的类

  • update.py

    • 数据变化时,服务器主动通知前端更新数据

  • send_data.py

    • 前端发起请求时,返回的数据

1、consumers.py

from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
from asgiref.sync import async_to_sync
import time
import json
# 接收到前端的websocket请求,直接向单个发送需要数据
from apps.websocket.send_data import base_sendclass AllDataConsumers(WebsocketConsumer):# 统一的房间名room_name = 'chat_all_data'def connect(self):cls = AllDataConsumersself.room_group_name = cls.room_name# 加入到房间组内, self.channel_name是当前async_to_sync(self.channel_layer.group_add)(self.room_group_name, self.channel_name)headers = self.scope['headers']print(headers)token = Nonefor key, value in headers:if key == b'token':token = value.decode('utf-8')print(token)# 同意创建连接self.accept()def disconnect(self, close_code):print('有浏览器退出了websocket!!!!')# Leave room groupasync_to_sync(self.channel_layer.group_discard)(self.room_group_name, self.channel_name)# Receive message from WebSocketdef receive(self, text_data=None, bytes_data=None):''':param text_data: 接收字符串类型的数据:param bytes_data:  接收bytes类型的数据:return:如果是浏览器直接请求时,就单独给这个浏览器返回结果,无需给房间组内的发送数据'''try:text_data_json = json.loads(text_data)the_type = text_data_json.get('type', 'none')except Exception as e:self.send(json.dumps({'code': 400, 'msg': '传递的数据请按照{"type":"xx","id":x,"params":{}}格式'}, ensure_ascii=False))self.disconnect(400)return#1、前端主动请求websocket时,拿到对应的数据,单独给该websocket返回数据send_data = base_send(text_data_json)if isinstance(send_data,dict):#需要给请求的前端返回数据self.send(json.dumps(send_data, ensure_ascii=False))else:#无需给请求的前端返回数据pass# 2、将数据发送到房间组内 (在非聊天模式无需这样操作)# async_to_sync(self.channel_layer.group_send)(#     self.room_group_name, {'type':'send_to_chrome','data':send_data}# )'''参数说明:self.room_group, 给哪个房间组发送数据,{'type':'send_to_chrome','data':send_data}send_to_chrome 是处理函数,在这里负责将房间组内的数据发送给浏览器send_data  要发送的数据'''# 自定义的处理房间组内的数据:实时推送就是使用这个来实现的def send_to_chrome(self, event):try:data = event.get('data')# 接收房间组广播数据,将数据发送给websocketself.send(json.dumps(data, ensure_ascii=False))except Exception as e:print('给全局的websocket推送消息失败')

2、send_data.py


def base_send(data:dict):'''功能:发起websocket请求时,给当前websocket返回数据:param data: {'type':'要操作的数据类型','id':'有id就是指定每个数据','params':{'page':'页码','page_size':'页面大小', }}:return:'''the_type = data.get('type')id = data.get('id')send_data = {'type':the_type,'data':'返回的数据'}#用户管理-搜索功能,用户信息是实时更新的if the_type == 'search_user_data':#前端发起websocket请求时,此类型时,无需返回数据return send_data

3、update.py

#channels包相关
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layerclass AllDataConsumersUpdate:'''功能:在http视图中,给房间组=chat_all_data 推送指定的消息'''def _make_channel_layer(self,send_data):''':param send_data: 在http视图中查询好的数据,要给房间组内所有的websocket对象发送数据'''channel_layer = get_channel_layer()#拿到房间组名group_name = 'chat_all_data'#给该房间组组内发送数据 注意是group_send方法async_to_sync(channel_layer.group_send)(group_name, #房间组名,给这个房间组发送数据{'type':'send_to_chrome', #处理这个房间组的消费者类必须有send_to_chrome方法'data':send_data   #要发送给websocket对象的数据})'''send_to_chrome: 该房间组对应的消费者,必须存在这个函数,在这个函数中进行将数据发送给房间组所有的websocket对象send_data : 查询出来的数据'''#用户管理-搜索用户页面-实时更新数据,由前端自己去获取数据def search_user_data(self):send_data = {'type':'search_user_data','page_update':1}#给房间发送数据self._make_channel_layer(send_data=send_data)return True

4、routings.py

from django.urls import path
from . import consumers# 这个变量是存放websocket的路由
socket_urlpatterns = [path('socket/all/',consumers.AllDataConsumers.as_asgi()),]

四、修改settings.py同级的asgi.py文件

asgi.py

import osfrom django.core.asgi import get_asgi_application#新的模块
from channels.routing import ProtocolTypeRouter, URLRouter
# 导入websocket的路由模块
from apps.websocket import routings#项目名,settings.py所在的目录名
os.environ.setdefault('DJANGO_SETTINGS_MODULE', '项目名.settings')application = ProtocolTypeRouter({# http路由走这里"http": get_asgi_application(),# chat应用下rountings模块下的路由变量socket_urlpatterns,就是存路由的列表"websocket": URLRouter(routings.socket_urlpatterns)
})

五、在视图函数中怎么发送websocket通知

from apps.websocket.update import websocket_update_obj #websocket推送数据的接口#在视图函数中直接调用需要的方法就可以实现推送了
websocket_update_obj.search_user_data()

将所有的推送方法都放到一个类中,可以很方便的进行管理,后期修改时,也可以实现统一的修改。

六、启动项目

python manage.py runserver 8005

看到 ASGI/Channels Version xxx 就说明启动成功,此时的django项目才支持websocket

七、测试

访问:EasySwoole-WebSocket在线测试工具

  • 1、服务地址:http://127.0.0.1:8005/socket/all/

  • 2、点击连接

  • 3、发送数据:{"type":"search_user_data"}

  • 4、点击发送

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/128193.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Flink1.18新特性生产环境应用的重点解读!

大家好,我是你们的群主王知无呀。 Flink 1.18已经于近期发布了。在这个新版本中新增了很多新的功能和特性。在这些特性中,有一些是生产环境非常重要的能力,大家在使用过程中可以重点参考和了解其中的原理。 算子级别状态保留时间TTL设置 首先…

GitHub经常打不开或者访问解决办法

访问慢或无法访问的原因:DNS解析是最为基础的一个环节。由于Github的服务器在全球各地,域名解析所需的时间也会不同,这就导致了在特定地区可能会出现Github无法正常访问的情况。 解决:查询到github对应的IP,然后在host…

精准测试:提高软件质量和用户满意度的利器

📢专注于分享软件测试干货内容,欢迎点赞 👍 收藏 ⭐留言 📝 如有错误敬请指正!📢交流讨论:欢迎加入我们一起学习!📢资源分享:耗时200小时精选的「软件测试」资…

腾讯云域名备案后,如何解析到华为云服务器Linux宝塔面板

一、购买域名并且进行备案和解析,正常情况下,购买完域名,如果找不到去哪备案,可以在腾讯云上搜索“备案”关键词就会出现了,所以这里不做详细介绍,直接进行步骤提示: 二、申请ssl证书&#xff0…

uniapp使用抖音微信自定义组件

tt.vue中使用video-player组件 用到的目录如下: pages.json {"path": "pages/Tabbar/tt/tt","style": {"navigationBarTitleText": "","enablePullDownRefresh": false,// 使用自定义组件"using…

Nginx服务器安装证书并启用SSL(acme.sh)

前提 您已购置vps服务器,例如阿里云全球站ecs、AWS EC2、Azure VM、GCP Compute等安全组已开启80、443端口,且访问源设置为0.0.0.0/0域名已设置A记录指向当前操作服务器,若您使用aws ec2,有公有 IPv4 DNS,可供使用 安…

2023年最新版潮乎盲盒源码含搭建教程

后台开发语言:后端 Laravel 框架开发 前端开发框架:uniappvue 环境配置: php7.4 mysql5.6 nginx1.22 redis(建议宝塔面板或 lnmp) 源码获取请自行百度:一生相随博客 一生相随博客致力于分享全网优质资源&#x…

Python条件判断的运用

问题 在生活中,我们可以通过判断条件是否成立,来决定执行哪个分支。选择语句有多种形式:if语句,if-else语句,if-elif-else语句等。 Python使用if条件判断语句来实现条件判断时,可以在多个循环中实现对问题的…

JAVA亡了?那么多岗位去哪了?

1.java现在有多卷? 虽然近年来出现了许多其他编程语言和技术。但JAVA依旧是热度最高的。它仍然被广泛用于大型企业应用、后端开发、Android应用开发以及嵌入式系统等领域。此外,Java在大数据、云计算和物联网等新兴领域也有着重要的地位。 因此&#x…

基于OR-Tools的装箱问题模型求解(PythonAPI)

装箱问题 一、背包问题(Knapsack problem)1.1 0-1背包模型基于OR-Tools的0-1背包问题求解(PythonAPI)导入pywraplp库数据准备声明MIP求解器初始化决策变量初始化约束条件目标函数调用求解器打印结果 1.2 多重背包问题(…

一篇博客读懂顺序表 —— Sequence-List

目录 一、顺序表的初始定义 1.1新建头文件和源文件 1.2 SeqList.h 中的准备工作 二、顺序表的初始化与销毁 三、首尾插入元素 四、首尾删除元素 五、中间插入元素 六、中间删除元素 七、查找指定元素下标 八、源代码 一、顺序表的初始定义 1.1新建头文件和源文件 当我…

流媒体服务实现H5实时预览视频

目录 背景方案业务实践细节注意 待办 背景 客户aws服务磁盘存储告急,最高可扩容16T。排查如下:主要是视频文件存在大量复制使用的情况。例如发布节目时复制、预览时复制,这样上传一份视频后最大会有四份拷贝(预览、普通发布、互动…

vue3简单写导航anchor示例(支持点击高亮和滚动判断高亮)

1. 点击anchor, 相应的anchorlink高亮 function anchorClick(index) { forceStop.value true; time Date.now(); wheelRef.value.children[index].scrollIntoView({ block: start, behavior: smooth }); // 给一些延时, 再点亮anchor, 同时不再限制scrol…

微信小程序 人工智能志愿者服务活动报名系统uniAPP+vue

基于java语言设计并实现了人工智能志愿者服务APP。该APP基于B/S即所谓浏览器/服务器模式,应用SpringBoot框架与HBuilder X技术,选择MySQL作为后台数据库。系统主要包括用户、志愿活动、活动报名、活动签到、服务职责、服务排行等功能模块。 本文首先介绍…

Zynq-Linux移植学习笔记之64- 国产ZYNQ在linux下配置国产5396芯片

1、背景介绍 复旦微ZYNQ通过SPI配置国产JEM5396,框图如下: 现在需要在linux下的应用程序内配置JEM5396的寄存器。其中FMQL和进口的XILINX ZYNQ类似,JEM5396和进口的BCM5396兼容。因此可以参考进口ZYNQ在linux下配置BCM5396过程。Zynq-Linux移…

云服务器 centos 部署 code-server 并配置 c/c++ 环境

将你的云服务器改为 centos 8 为什么要将云服务器的操作系统改成 centos 8 呢?原因就是 centos 7 里面的配置满足不了 code-server 的需求。如果你使用的是 centos 7 那么就需要你升级一些东西,这个过程比较麻烦。我在 centos 7 上面运行 code-server 的…

k8s、pod

Pod k8s中的port【端口:30000-32767】 port :为Service 在 cluster IP 上暴露的端口 targetPort:对应容器映射在 pod 端口上 nodePort:可以通过k8s 集群外部使用 node IP node port 访问Service containerPort:容…

velero备份k8s集群

流程图 velero备份原理 本地 Velero 客户端发送备份指令。Kubernetes 集群内就会创建一个 Backup 对象。BackupController 监测 Backup 对象并开始备份过程。BackupController 会向 API Server 查询相关数据。BackupController 将查询到的数据备份到远端的对象存储。 velero的…

osg三角带

案例1 #include <osg/Geode> #include <osg/Geometry> #include <osgDB/Registry> #include <osgDB/WriteFile> #include <osg/Notify> #include <osg/PrimitiveSet> #include <osgViewer/Viewer> #include <osgUtil/Optimizer&g…

【数据结构】希尔排序

文章目录 前言一、希尔排序的演示图例二、希尔排序&#xff1a;插入排序的优化版本☆三、核心算法思路四、算法思路步骤&#xff08;一&#xff09;预排序 gap>1&#xff08;二&#xff09;gap1 插入排序 完成排序收尾 五、码源详解&#xff08;1&#xff09;ShellSort1 ——…