LuckySheet协同编辑后端示例(Django+Channel,Websocket通信)

其他的配置不赘述了,直接网上搜一下django使用channel的配置方法

我初步研究通道先用的内存
在setting文件中
 

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels.layers.InMemoryChannelLayer",
    },
}

这里我重点说一下luckysheet源码的部分

首先是websocket,这部分代码在源码的server.js中,通过研究源码,才解决了问题

pako解压的问题尝试了很多次都没不太对,于是直接把pako部分的源码给注释掉了,直接传过去的就是json字符串

} else {
            // let msg = pako.gzip(encodeURIComponent(JSON.stringify(d)), {to: "string"});
			let msg = JSON.stringify(d);
			//console.info(msg);
            if (_this.websocket != null) {
                _this.websocket.send(msg);
            }
        }

后端的消费者类的主要代码如下

from channels.generic.websocket import AsyncJsonWebsocketConsumer
from urllib.parse import parse_qs
import json

class TableConsumer(AsyncJsonWebsocketConsumer):
    table = None
    gridKey = None

    async def connect(self):
        query = self.scope['query_string'].decode('utf-8')
        t = parse_qs(query)['t'][0]
        self.gridKey = parse_qs(query)['g'][0]
        await self.channel_layer.group_add(f'table_{self.gridKey}', self.channel_name)
        await self.accept()
        print('建立连接')

    async def disconnect(self, close_code):
        print('断开连接')
        await self.channel_layer.group_discard(f'table_{self.gridKey}', self.channel_name)

    async def receive(self, text_data=None, bytes_data=None):
        # 使用json.loads方法将JSON字符串解析为Python的字典对象
        if text_data !='rub':
            parsed_data = json.loads(text_data)
            print(parsed_data)
            # 这里构造要广播的数据
            broadcast_data = dict()
            broadcast_data['type'] = 3
            broadcast_data['data'] = text_data
            broadcast_data['username'] = 'test'
            broadcast_event = {
                "type": "broadcast_message",
                "message": broadcast_data
            }
            # 向对应的组发送广播事件,触发broadcast_message方法来实际发送给组内成员
            await self.channel_layer.group_send(f'table_{self.gridKey}', broadcast_event)

    async def broadcast_message(self, event):
        message = event["message"]
        await self.send_json(message)

之前对websocket和channel不太了解,看了前端代码后把type和message给改了,后来多次尝试发现这个千万别改,他会在send的时候卡住而且不报任何错误(因为协程),如果是广播的话只需要修改broadcast_data的内容就行,通过解读前端的代码,在后端构建返回的json,成果把type=3的内容实现了,也就是鼠标移动的部分

else if(type == 3){ //多人操作不同选区("t": "mv")(用不同颜色显示其他人所操作的选区)
	                let id = data.id;
	                let username = data.username;
	                let item = JSON.parse(data.data);
	                let type = item.t,
	                    index = item.i,
	                    value = item.v;

剩余的部分我就先不写了,具体操作应该是根据前端过来的json内容来自行判断返回的type,然后进行消息的分发!!!!

重点:读源码读源码读源码!!!!!

又写了两种type,批量的没写到type=4的情况,因为他前端写的感觉有问题还造成了后端的麻烦,于是后端写成多个type=2了,增加了一点点服务器压力

from channels.generic.websocket import AsyncJsonWebsocketConsumer
from urllib.parse import parse_qs
import json

from pyasn1_modules.rfc5639 import brainpoolP160r1


class TableConsumer(AsyncJsonWebsocketConsumer):
    table = None
    gridKey = None

    async def connect(self):
        query = self.scope['query_string'].decode('utf-8')
        t = parse_qs(query)['t'][0]
        self.gridKey = parse_qs(query)['g'][0]
        await self.channel_layer.group_add(f'table_{self.gridKey}', self.channel_name)
        await self.accept()
        print('建立连接')

    async def disconnect(self, close_code):
        print('断开连接')
        await self.channel_layer.group_discard(f'table_{self.gridKey}', self.channel_name)

    async def receive(self, text_data=None, bytes_data=None):
        # 使用json.loads方法将JSON字符串解析为Python的字典对象
        if text_data !='rub':
            parsed_data = json.loads(text_data)
            print(parsed_data)
            if parsed_data['t'] == 'mv':
                # 这里构造要广播的事件数据,假设要原封不动广播接收到的数据,将其放入'message'字段
                broadcast_data = dict()
                broadcast_data['type'] = 3
                broadcast_data['data'] = text_data
                broadcast_data['username'] = 'test'
                broadcast_event = {
                    "type": "broadcast_message",
                    "message": broadcast_data
                }
                # 向对应的组发送广播事件,触发broadcast_message方法来实际发送给组内成员
                await self.channel_layer.group_send(f'table_{self.gridKey}', broadcast_event)
            if parsed_data['t'] == 'v':
                # 这里构造要广播的事件数据,假设要原封不动广播接收到的数据,将其放入'message'字段
                broadcast_data = dict()
                broadcast_data['type'] = 2
                broadcast_data['data'] = text_data
                broadcast_data['username'] = 'test'
                broadcast_event = {
                    "type": "broadcast_message",
                    "message": broadcast_data
                }
                # 向对应的组发送广播事件,触发broadcast_message方法来实际发送给组内成员
                await self.channel_layer.group_send(f'table_{self.gridKey}', broadcast_event)
            if parsed_data['t'] == 'rv':

                row = parsed_data['range']['row']
                column = parsed_data['range']['column']
                for j in range(column[0], column[1]+1):
                    numj = j-column[0]
                    for i in range(row[0], row[1] + 1):
                        numi = i-row[0]
                        try:
                            broadcast_data = dict()
                            broadcast_data['type'] = 2
                            # data = list()
                            broadcast_data['username'] = 'test'
                            data = dict()
                            data['t'] = 'v'
                            data['i'] = 0
                            data['v'] = parsed_data['v'][numi][numj]
                            data['r'] = i
                            data['c'] = j
                            broadcast_data['data'] = json.dumps(data)
                            broadcast_event = {
                                "type": "broadcast_message",
                                "message": broadcast_data
                            }
                            await self.channel_layer.group_send(f'table_{self.gridKey}', broadcast_event)

                        except Exception as e:
                            print(e)



    async def broadcast_message(self, event):
        message = event["message"]
        await self.send_json(message)

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

AnythingLLM - 任何文档资源内容转换为任何LLM

更多AI开源软件: AI开源 - 小众AIhttps://www.aiinn.cn/sources 一个全栈应用程序,使您能够将任何文档、资源或内容转换为任何 LLM 都可以在聊天期间用作参考的上下文。此应用程序允许您选择要使用的 LLM 或矢量数据库,并支持多用户管理和权…

PDF内容提取,MinerU使用

准备环境 # python 3.10 python3 -m pip install huggingface_hub python3 -m pip install modelscope python3 -m pip install -U magic-pdf[full] --extra-index-url https://wheels.myhloli.com下载需要的模型 import json import osimport requests from huggingface_hub…

【阅读记录-章节3】Build a Large Language Model (From Scratch)

目录 3 Coding attention mechanisms3.1 The problem with modeling long sequences背景:注意力机制的动机 3.2 Capturing data dependencies with attention mechanismsRNN的局限性与改进Transformer架构的革命 3.3 Attending to different parts of the input wit…

Kubernetes配置管理ConfigMap、Secret

Your burden will become a gift, and your suffering will light your way. 应用部署的一个最佳实践是将应用所需的配置信息与程序分离,这样可以使应用程序被更好地复用,通过不同的配置也能实现更灵活的功能。将应用打包为容器镜像后,可以通过环境变量或者外挂文件的方式在…

141. Sprite标签(Canvas作为贴图)

上节课案例创建标签的方式,是把一张图片作为Sprite精灵模型的颜色贴图,本节给大家演示把Canvas画布作为Sprite精灵模型的颜色贴图,实现一个标签。 注意:本节课主要是技术方案讲解,默认你有Canvas基础,如果没有Canvas基…

「OpenCV交叉编译」ubuntu to arm64

Ubuntu x86_64 交叉编译OpenCV 为 arm64OpenCV4.5.5、cmake version 3.16.3交叉编译器 gcc-arm-10.2-2020.11-x86_64-aarch64-none-linux-gnu 可在arm或linaro官网下载所需版本,本文的交叉编译器可点击链接跳转下载 Downloads | GNU-A Downloads – Arm Developer L…

鸿蒙网络编程系列48-仓颉版UDP回声服务器示例

1. UDP回声服务器简介 回声服务器指的是这样一种服务器,它接受客户端的连接,并且把收到的数据原样返回给客户端,本系列的第2篇文章《鸿蒙网络编程系列2-UDP回声服务器的实现》中基于ArkTS语言在API 9的环境下实现了UDP回声服务器&#xff0c…

【WPF】Prism学习(七)

Prism Dependency Injection 1.注册类型(Registering Types) 1.1. Prism中的服务生命周期: Transient(瞬态):每次请求服务或类型时,都会获得一个新的实例。Singleton(单例&#xf…

springboot基于Hadoop的NBA球员大数据分析与可视化(1)(6)

摘 要 科学技术日新月异,人们的生活都发生了翻天覆地的变化,NBA球员大数据分析与可视化系统当然也不例外。过去的信息管理都使用传统的方式实行,既花费了时间,又浪费了精力。在信息如此发达的今天,可以通过网络这个媒…

Q3净利增长超预期,文心大模型调用量大增,百度未来如何分析?

首先,从百度发布的2024年第三季度财务报告来看,其净利润同比增长17%,超出了市场预期,显示出百度整体财务表现的强劲。这一增长不仅体现在总营收和百度核心营收上,更具体地反映在归属百度核心的净利润上,这标…

Vscode/Code-server无网环境安装通义灵码

Date: 2024-11-18 参考材料:https://help.aliyun.com/zh/lingma/user-guide/individual-edition-login-tongyi-lingma?spma2c4g.11186623.0.i0 1. 首先在vscode/code-server插件市场中安装通义插件,这步就不细说了。如果服务器没网,会问你要…

开源TTS语音克隆神器GPT-SoVITS_V2版本地整合包部署与远程使用生成音频

文章目录 前言1.GPT-SoVITS V2下载2.本地运行GPT-SoVITS V23.简单使用演示4.安装内网穿透工具4.1 创建远程连接公网地址 5. 固定远程访问公网地址 前言 本文主要介绍如何在Windows系统电脑使用整合包一键部署开源TTS语音克隆神器GPT-SoVITS,并结合cpolar内网穿透工…

实战 | C#中使用YoloV8和OpenCvSharp实现目标检测 (步骤 + 源码)

导 读 本文主要介绍在C#中使用YoloV8实现目标检测,并给详细步骤和代码。 详细步骤 【1】环境和依赖项。 需先安装VS2022最新版,.NetFramework8.0,然后新建项目,nuget安装 YoloSharp,YoloSharp介绍: https://github.com/dme-compunet/YoloSharp 最新版6.0.1,本文…

IDE配置tomcat

1.导航到 Tomcat 安装目录 E:\apache-tomcat-9.0.95-windows-x64\apache-tomcat-9.0.95 2.启动 Tomcat 服务:bin\startup.bat

python读取Oracle库并生成API返回Json格式

一、安装必要的库 首先,确保已经安装了以下库: 有网模式 pip install flask pip install gevent pi install cx_Oracle离线模式: 下载地址:https://pypi.org/simple/flask/ # a. Flask Werkzeug-1.0.1-py2.py3-none-any.whl J…

MAC借助终端上传jar包到云服务器

前提:保证工程本地已打包完成:图中路径即为项目的target目录下已准备好的jar包 第一步:打开终端(先不要连接自己的服务器),输入下面的上传命令: scp /path/to/local/app.jar username192.168.1…

Python数据分析NumPy和pandas(四十、Python 中的建模库statsmodels 和 scikit-learn)

主要学习两个流行的建模工具包,statsmodels 和 scikit-learn。 一、pandas 与模型代码之间的接口 模型开发的常见工作流程是使用 pandas 进行数据加载和清理,然后再切换到建模库来构建模型本身。模型开发过程的一个重要部分在机器学习中称为特征工程&a…

实操案例|TinyVue树表+动态行合并

本文由孟智强同学原创。 背景 团队某个小项目切换 UI 框架,要将 Element 换成 TinyVue。期间遇到一个树表形式的业务表格,支持多级下钻,且第一列有合并行。当初用 Element 实现这个表格时费了一些周折,料想 TinyVue 上场应该也不…

Mesh路由组网

Mesh无线网格网络,多跳(multi-hop)网络,为解决全屋覆盖信号,一般用于家庭网络和小型企业 原理 网关路由器(主路由,连接光猫),Mesh路由器(子路由,…

基于Windows系统用C++做一个点名工具

目录 一、前言 二、主要技术点 三、准备工作 四、主界面 1.绘制背景图 2、实现读取花名册功能 3.实现遍历花名册功能 4.实现储存功能 4.1创建数据库 4.2存储数据到数据库表 4.3读取数据库表数据 一、前言 人总是喜欢回忆过去,突然回忆起…