Django框架:使用channels实现websocket,配置和项目实际使用
一、基本配置
依赖包:
Django==3.2 django-cors-headers==3.5.0 redis==4.6.0 #操作redis数据库的 channels==3.0.0 #websocket channels-redis==4.1.0 #通道层需要,依赖redis包
项目目录结构:
study_websocket
--study_websocket
--__init__.py
--settings.py
--asgi.py
--wsgi.py
--urls.py
--chat
--routings.py
--consumers.py
--update.py
--urls.py
--views.py
1.1、settings.py配置
1、注册跨域、channels、chat应用
INSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles','corsheaders', #前后端跨域'chat.apps.WebsocketConfig',#专门用于写websocket的方法'channels', #django通过其实现websocket
]
2、跨域配置
##### 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' #请求头允许自定义的字符串
)
3、channels需要的配置
WSGI_APPLICATION = 'study_websocket.wsgi.application'
#channels使用需要添加ASGI_APPLICATION
ASGI_APPLICATION = 'study_websocket.asgi.application'
#通道层:开发阶段使用内存
CHANNEL_LAYERS = {"default": {"BACKEND": "channels.layers.InMemoryChannelLayer"}
}
1.2、在chat应用新增routings.py 和 consumers.py
1、consumers.py设置一个简单消费者
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
from asgiref.sync import async_to_sync
import timeclass ChatView(WebsocketConsumer):def websocket_connect(self, message):#客户端与服务端进行握手时,会触发这个方法#服务端允许客户端进行连接,就是握手成功self.accept()def websocket_receive(self, message):#接收到客户端发送的数据recv = message.get('text')print('接收到的数据,',recv)if recv == 'close':#服务的主动断开连接print('服务器断开连接')self.close()else:#客户端向服务端发送数据self.send(f'我收到了,{time.strftime("%Y-%m-%d %H:%M:%S")}')def websocket_disconnect(self, message):#客户端端口连接时,会触发该方法,断开连接print('客户端断开连接')raise StopConsumer()
2、配置routings.py
from django.urls import path
from . import consumers#这个变量是存放websocket的路由
socket_urlpatterns = [path('chat/socket/',consumers.ChatView.as_asgi()),
]
1.3、修改跟settings.py同级目录下的asgi.py
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter,URLRouter
#导入chat应用中的路由模块
from chat import routingsos.environ.setdefault('DJANGO_SETTINGS_MODULE', 'study_websocket.settings')
application = ProtocolTypeRouter({#http路由走这里"http":get_asgi_application(),#chat应用下rountings模块下的路由变量socket_urlpatterns"websocket":URLRouter(routings.socket_urlpatterns)
})
1.4、启动项目
启动命令:python manage.py runserver 8888
启动提示:如下就是配置成功了
在线测试websocket的网站:
EasySwoole-WebSocket在线测试工具EasySwoole在线WebSocket测试工具http://www.easyswoole.com/wstool.html
服务地址:ws://127.0.0.1:8888/chat/socket/ 点击开启连接
连接成功后,就可以向服务端发送数据了。
二、房间组使用(聊天室:待更新)
三、房间组使用(非聊天室)
概述:
data = {'type':'xxx'}
1、前端只想维护一个全局的websocket对象,通过发送的数据中type的不同获取到不同的数据。
2、在后端给前端主动推送数据时,也是通过这个type来确定要重新渲染的数据。
构建想法:
1、设置一个处理全局websocket的消费者类
2、设置一个全局websocket都进入的房间组
3、在chat应用下新建一个update.py: websocket返回数据 和主动推送数据都放到这个模块中
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 websocket.update 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']token = Nonefor key,value in headers:if key == b'token':token = value.decode('utf-8')if token:print(token)else: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':'传递的数据有问题'},ensure_ascii=False))self.disconnect(400)return#个人信息:所有的老人信息if the_type == 'all_patient_page_data':send_data = base_send(text_data_json)self.send(json.dumps(send_data,ensure_ascii=False))#来访登记:进行中的来访登记if the_type == 'all_active_visit_data':send_data = base_send(text_data_json)self.send(json.dumps(send_data,ensure_ascii=False))#自定义的处理房间组内的数据def send_to_chrome(self, event):try:data = event.get('data')#接收房间组广播数据,将数据发送给websocketself.send(json.dumps(data,ensure_ascii=False))except Exception as e:error_logger.exception(str(e),'给全局的websocket推送消息失败')
update.py
import json
from datetime import datetime,timedelta
from django.db.models import Q#channels包相关
from asgiref.sync import async_to_sync
from channels.layers import get_channel_layerdef base_send(data:dict):'''功能:发起websocket请求时,给当前websocket返回查询到的数据'''the_type = data.get('type')id = data.get('id')send_data = {'type':the_type,}#个人管理-首次进入时,没有点击搜索时,这个需要实时获取if the_type == 'all_patient_page_data':send_data['data'] = '数据库查询到的数据:个人管理'return send_data#来访登记:进行中的来访记录if the_type == 'all_active_visit_data':send_data['data'] = '数据库查询到的数据:来访记录'return send_data#class AllDataConsumersUpdate:'''功能:在http视图中,给房间组=chat_all_data 推送指定的消息在视图函数中,某些数据更新了,需要通知所有的websocket对象'''def _make_channel_layer(self,send_data):''':param send_data: 在http视图中查询好的数据,要给房间组内所有的websocket对象发送数据'''channel_layer = get_channel_layer()#拿到房间组名group_name = 'chat_all_data'#给该房间组组内发送数据async_to_sync(channel_layer.group_send)(group_name,{'type':'send_to_chrome', #消费者中处理的函数'data':send_data})#个人信息:def all_patient_page_data(self):try:send_data = {'type':'all_patient_page_data','data':'更新数据了,个人信息'}#把更新的数据发送到房间组内self._make_channel_layer(send_data=send_data) except Exception as e:pass#来访登记:def all_active_visit_data(self):try:send_data = {'type':'all_patient_page_data','data':'更新数据了,来访登记'}#把更新的数据发送到房间组内self._make_channel_layer(send_data=send_data) except Exception as e:error_logger.exception(str(e))
rountings.py
from django.urls import path
from . import consumers#这个变量是存放websocket的路由
socket_urlpatterns = [path('chat/socket/',consumers.ChatView.as_asgi()),path('socket/all/',consumers.AllDataConsumers.as_asgi()),
]
两个视图函数
from chat.update import AllDataConsumersUpdate #2023-07-25:模拟来访记录变化 update = AllDataConsumersUpdate() update.all_active_visit_data()
from chat.update import AllDataConsumersUpdate
#2023-07-25:模拟个人信息编变化 update = AllDataConsumersUpdate() update.all_patient_page_data()
1、先使用测试网站连接上:
EasySwoole-WebSocket在线测试工具
2、再访问写的两个视图函数,看websocket是否返回数据
业务逻辑:
1、创建连接时,把websocket对象放到同一个房间组内
2、当是websocket对象主动给后端发送数据时,后端只对这个websocket对象返回数据
3、当在视图中调用主动推送的方法,
a.把数据发送到房间组内
b.通过设置好的处理方法send_to_chrome 来实现从房间组内拿到数据,发送给websocket对象
相关文章:

Django框架:使用channels实现websocket,配置和项目实际使用
一、基本配置 依赖包: Django3.2 django-cors-headers3.5.0 redis4.6.0 #操作redis数据库的 channels3.0.0 #websocket channels-redis4.1.0 #通道层需要,依赖redis包项目目录结构: study_websocket --study_websocket --__init__.py --s…...

基于RK3588+FPGA+AI算法定制的智慧交通与智能安防解决方案
随着物联网、大数据、人工智能等技术的快速发展,边缘计算已成为当前信息技术领域的一个热门话题。在物联网领域,边缘计算被广泛应用于智慧交通、智能安防、工业等多个领域。因此,基于边缘计算技术的工业主板设计方案也受到越来越多人的关注。…...

AI面试官:LINQ和Lambda表达式(一)
AI面试官:LINQ和Lambda表达式(一) 当面试官面对C#中关于LINQ和Lambda表达式的面试题时,通常会涉及这两个主题的基本概念、用法、实际应用以及与其他相关技术的对比等。以下是一些可能的面试题目,附带简要解答和相关案…...

FPGA学习——FPGA利用状态机实现电子锁模拟
文章目录 一、本次实验简介二、源码及分析三、总结 一、本次实验简介 本次是实验是为了利用状态机模拟电子锁,相关要求如下: 顺序输入4位密码,密码为1234,用按键来键入密码用led灯指示键入第几位密码,(博…...

Bert经典变体学习
ALBert ALBERT就是为了解决模型参数量大以及训练时间过长的问题。ALBERT最小的参数只有十几M, 效果要比BERT低1-2个点,最大的xxlarge也就200多M。可以看到在模型参数量上减少的还是非常明显的,但是在速度上似乎没有那么明显。最大的问题就是这种方式其实…...

uniapp checkbox radio 样式修改
文章目录 通过查看代码,发现 before部分是设置样式的主要属性 我们要设置的话,就要设置checkbox::before的属性。 其中的content表示内容,比如内部的对勾 那么我们设置的时候,比如设置disabletrue的时候或者checkedtrue的时候&…...

电脑重启后VScode快捷方式失效,找不到Code.exe
问题描述 下班回家关了部分程序就直接关机了,回家后重启电脑发现vscode的快捷方式就失效了,提示Code.exe已被移动或删除。 解决方法 查看你的vscode安装目录,Microsoft VS Code目录下大概率会存在一个名为_的文件夹,然后会发现…...

C语言实现扫雷游戏
test.c源文件 - 扫雷游戏测试 game.h头文件 - 扫雷游戏函数的声明 game.c源文件 - 扫雷游戏函数的实现 1.布置雷 -- 存放雷的雷盘 9*9 数组设计成11*11 上下左右方各多一行,保证周围8的范围 雷 - 1 不是雷 - 0 2.排查雷 主题测试源文件代码 &…...

蓝图节点编辑器
打印字符串 第02章 蓝图结构 03 -注释和重新路由_哔哩哔哩_bilibili 第02章 蓝图结构 04 - 变量_哔哩哔哩_bilibili 第03章 蓝图简易门 01 - 箱子碰撞_哔哩哔哩_bilibili 第03章 蓝图简易门 02 - 静态Mesh和箭头_哔哩哔哩_bilibili 第03章 蓝图简易门 03 - 设置相对旋转节点_哔…...

MySql 知识大汇总
数据库索引 数据库索引是一种数据结构,用于提高数据库查询的速度和效率。索引可以看作是表中一列或多列的值的快速查找方式,类似于书籍的目录。通过创建索引,可以减少数据库的扫描量,加快数据的检索速度。 常见的索引类型 常见…...

深入浅出Pytorch函数——torch.sum
分类目录:《深入浅出Pytorch函数》总目录 相关文章: 深入浅出Pytorch函数——torch.Tensor 函数torch.sum有两种形式: torch.sum(input, *, dtypeNone):返回输入张量input所有元素的和。torch.sum(input, dim, keepdimFalse, *,…...

Git克隆文件不显示绿色勾、红色感叹号等图标
1、问题 Git和TorToiseGit安装后,Git克隆的文件不会显示绿色勾、红色感叹号等图标。 2、检查注册表 2.1、打开注册表 (1)WinR打开运行窗口,输入regedit,点击确定,打开注册表编辑器。 2.2、找如下路径 (1)找到路径 计算机\HKEY_…...

SOC FPGA之HPS模型设计(一)
目录 一、建立HPS硬件系统模型 1.1 GHRD 1.2 从0开始搭建HPS 1.2.1 FPGA Interfaces 1.2.1.1 General 1.2.1.2 AXI Bridge 1.2.1.3 FPGA-to-HPS SDRAM Interface 1.2.1.4 DMA Peripheral Request 1.2.1.5 Interrupts 1.2.1.6 EMAC ptp interface 1.2.2 Peripheral P…...

解决openstack重启swift服务后报错
swift重启报错 问题描述解决办法 问题描述 swift服务正常状态如下 [rootcontroller ~]# swift statAccount: AUTH_8bde12ff804e42498661b7454994c446Containers: 0Objects: 0Bytes: 0X-Put-Timestamp: 1690507907.67931X-Timestamp: 1690507907.67931X-Trans-Id: tx56d22fa13…...

[Linux]进程控制详解!!(创建、终止、等待、替换)
hello,大家好,这里是bang___bang_,在上两篇中我们讲解了进程的概念、状态和进程地址空间,本篇讲解进程的控制!!包含内容有进程创建、进程等待、进程替换、进程终止!! 附上前2篇文章…...

全面适配 | 走近openGauss数据库+鲲鹏欧拉操作系统
引入 全面适配 | openEuler操作系统 openGauss数据库 开篇 1、openEuler欧拉操作系统 百度百科:openEuler是覆盖全场景的创新平台,在引领内核创新,夯实云化基座的基础上,面向计算架构互联总线、存储介质发展新趋势,…...

2023Robocom CAIP省赛 第四题 相对论大师
原题链接: PTA | 程序设计类实验辅助教学平台 题面: 在某个直播间里,观众常常会发送类似这样的弹幕: 鱼越大,鱼刺越大;鱼刺越大,肉越少;肉越少,鱼越小;所以鱼…...

【TypeScript】TS入门级基础学习(一)
【TypeScript】TS入门级基础学习(一) 一、前言 TypeScript 是一种用于应用程序规模的 JavaScript 语言。 TypeScript 向 JavaScript 添加了可选类型,支持用于任何浏览器、任何主机、任何操作系统的大规模 JavaScript 应用程序的工具。 Type…...

jenkins执行jmeter时,报Begin size 1 is not equal to fixed size 5
jenkins执行jmeter脚本的时候一直提示如下错误: Tidying up ... Fri Jul 28 17:03:53 CST 2023 (1690535033178) Error generating the report: org.apache.jmeter.report.dashboard.GenerationException: Error while processing samples: Consumer failed wi…...

在 “小小容器” WasmEdge 里运行小小羊驼 llama 2
昨天,特斯拉前 AI 总监、OpenAI 联合创始人 Andrej Karpathy 开源了 llama2.c 。 只用 500 行纯 C 语言就能训练和推理 llama 2 模型的框架,没有任何繁杂的 python 依赖。这个项目一推出就受到大家的追捧,24 小时内 GitHub 收获 4000 颗星&am…...

【C#】async和await 续
前言 在文章《async和await》中,我们观察到了一下客观的规律,但是没有讲到本质,而且还遗留了一个问题: 这篇文章中,我们继续看看这个问题如何解决! 我们再看看之前写的代码: static public void TestWait2() {var t…...

【Matlab】基于粒子群优化算法优化BP神经网络的数据回归预测(Excel可直接替换数据)
【Matlab】基于粒子群优化算法优化 BP 神经网络的数据回归预测(Excel可直接替换数据) 1.模型原理2.数学公式3.文件结构4.Excel数据5.分块代码5.1 fun.m5.2 main.m6.完整代码6.1 fun.m6.2 main.m7.运行结果1.模型原理 基于粒子群优化算法(Particle Swarm Optimization, PSO)…...

QPainter绘制雷达界面
文章目录 功能实现定义的结构体定义的函数效果图gitee源码链接 功能实现 相较于上一版,这一版添加的功能有: 1、自适应窗口 2、扫描方式(圆周扫描、扇形扫描(指定起始角度和结束角度)) 3、扫描方向&#x…...

flutter:BottomNavigationBar和TabBar
区别 BottomNavigationBarr和TabBar都是用于创建导航栏的组件,但它们有一些区别。 位置不同:BottomNavigationBar通常位于屏幕底部,用于主要导航;而TabBar通常位于屏幕顶部或底部,用于切换不同的视图或页面。 样式不…...

【图论】Prim算法
一.介绍 Prim算法是一种用于解决最小生成树问题的贪心算法。最小生成树问题是指在一个连通无向图中找到一个生成树,使得树中所有边的权重之和最小。 Prim算法的基本思想是从一个起始顶点开始,逐步扩展生成树,直到覆盖所有顶点。具体步骤如下…...

第九十二回 在Flutter中解析JSON数据
文章目录 概念介绍解析方法convert库插件工具 示例代码经验总结 我们在上一章回中介绍了"对dio库进行封装"相关的内容,本章回中将介绍 如何在Flutter中解析JSON数据.闲话休提,让我们一起Talk Flutter吧。 概念介绍 我们在前面章回中介绍了通…...

银河麒麟安装mysql数据库(mariadb)-银河麒麟安装JDK-银河麒麟安装nginx(附安装包)
银河麒麟离线全套安装教程(手把手教程) 1.银河麒麟服务器系统安装mysql数据库(mariadb) 2.银河麒麟桌面系统安装mysql数据库(mariadb) 3.银河麒麟服务器系统安装JDK 4.银河麒麟桌面系统安装JDK 5.银河麒麟…...

文件上传
js绕过 打开网页尝试上传一句话木马,发现只能上传图片文件 审计源代码,发现使用一个checkfile函数js对文件类型进行了屏蔽 于是我们修改网页代码,去除返回值的检查函数 checkFile() 上传成功,使用蚁剑连接 连接成功 .htaccess绕…...

tinkerCAD案例:22. Backpack Zipper Pull 背包拉链头
tinkerCAD案例:21. Custom Stamp 定制印章 原文 tinkerCAD案例:22. Backpack Zipper Pull 背包拉链头 Lesson Overview: 课程概述: Now we’re going to make a zipper pull! 现在我们要做一个拉链头! Your backpack, howev…...

Unity 性能优化四:UI耗时函数、资源加载、卸载API
UI耗时函数 1.1 Canvas.SendWillRenderCanvases 这个函数是由于自身UI的更新,产生的耗时 1. 这里更新的是vertex 属性,比如 color、tangent、position、uv,修改recttransform的position、scale,rotation并不会导致顶点属性改变…...