Django结合websocket实现分组的多人聊天

ops/2024/12/15 14:27:28/

其他地方和上一篇大致相同,上一篇地址点击进入,

改动点1:在setting.py中最后再添加如下配置:

#  多人聊天
CHANNEL_LAYERS = {"default":{"BACKEND": "channels.layers.InMemoryChannelLayer"}
}

因此完整的settings.py文件如下:

"""
Django settings for ws_demo project.Generated by 'django-admin startproject' using Django 4.2.For more information on this file, see
https://docs.djangoproject.com/en/4.2/topics/settings/For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.2/ref/settings/
"""from pathlib import Path# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.2/howto/deployment/checklist/# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'django-insecure-&62q15t&-it1jwy4o^&xsh(!fj3cm)#7=r+z12yw3j@x@kox2x'# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = TrueALLOWED_HOSTS = []# Application definitionINSTALLED_APPS = ['django.contrib.admin','django.contrib.auth','django.contrib.contenttypes','django.contrib.sessions','django.contrib.messages','django.contrib.staticfiles',"channels",  # 添加channels"app01.apps.App01Config" # 添加app01
]MIDDLEWARE = ['django.middleware.security.SecurityMiddleware','django.contrib.sessions.middleware.SessionMiddleware','django.middleware.common.CommonMiddleware','django.middleware.csrf.CsrfViewMiddleware','django.contrib.auth.middleware.AuthenticationMiddleware','django.contrib.messages.middleware.MessageMiddleware','django.middleware.clickjacking.XFrameOptionsMiddleware',
]ROOT_URLCONF = 'ws_demo.urls'TEMPLATES = [{'BACKEND': 'django.template.backends.django.DjangoTemplates','DIRS': [],'APP_DIRS': True,'OPTIONS': {'context_processors': ['django.template.context_processors.debug','django.template.context_processors.request','django.contrib.auth.context_processors.auth','django.contrib.messages.context_processors.messages',],},},
]WSGI_APPLICATION = 'ws_demo.wsgi.application'# Database
# https://docs.djangoproject.com/en/4.2/ref/settings/#databasesDATABASES = {'default': {'ENGINE': 'django.db.backends.sqlite3','NAME': BASE_DIR / 'db.sqlite3',}
}# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validatorsAUTH_PASSWORD_VALIDATORS = [{'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',},{'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',},{'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',},{'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',},
]# Internationalization
# https://docs.djangoproject.com/en/4.2/topics/i18n/LANGUAGE_CODE = 'en-us'TIME_ZONE = 'UTC'USE_I18N = TrueUSE_TZ = True# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.2/howto/static-files/STATIC_URL = 'static/'# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-fieldDEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'ASGI_APPLICATION = "ws_demo.asgi.application"#  多人聊天
CHANNEL_LAYERS = {"default":{"BACKEND": "channels.layers.InMemoryChannelLayer"}
}

2、app01下view.py中的内容如下:

from django.shortcuts import render
# Create your views here.def index(request):qq_group_num = request.GET.get("num")return render(request, 'index.html', {"qq_group_num": qq_group_num})

3、index.html中的内容如下:

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><title>Title</title><style>.message {height: 300px;border: 1px solid #dddddd;width: 100%;}</style>
</head><body>
<div class="message" id="message"></div>
<div><input type="text" placeholder="请输入" id="txt"><input type="button" value="发送" onclick="sendMsg()"><input type="button" value="关闭连接" onclick="closeConn()"><input type="button" value="重新建立连接" onclick="connect()">
</div><script>var socket = null;function connect() {socket = new WebSocket("ws:/127.0.0.1:8000/room/{{qq_group_num}}/");// 连接完成以后 客户端自动触发socket.onopen = function (event) {let tag = document.createElement("div")tag.innerHTML = "连接已建立"document.getElementById("message").appendChild(tag)}// 回调函数 当服务端有消息发送到时,自动触发socket.onmessage = function (event) {console.log(event.data);let tag = document.createElement("div");tag.innerText = event.data;document.getElementById("message").appendChild(tag)}// 当连接关闭时,触发socket.onclose = function (event) {let tag = document.createElement("div")tag.innerHTML = "连接已断开"document.getElementById("message").appendChild(tag)}}function sendMsg() {let tag = document.getElementById("txt")socket.send(tag.value)}function closeConn() {// 向服务端发送断开连接socket.close();}connect()
</script>
</body>
</html>

consumers.py中的内容如下:

from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
from asgiref.sync import async_to_syncclass ChatConsumer(WebsocketConsumer):  # 继承WebsocketConsumerdef websocket_connect(self, message):print("有人进行连接了。。。。")# 有客户端向后端发送 WebSocket 连接的请求时,自动触发(握手)self.accept()#  获取群号,获取路由匹配中的群号group = self.scope["url_route"]["kwargs"].get("group")# 将这个客户端连接对象加入到某个组里边(内存 or redis) async_to_sync 将异步方法转换为同步方法async_to_sync(self.channel_layer.group_add)(group, self.channel_name)def websocket_receive(self, message):# 浏览器基于 WebSocket 向后端发送数据,自动触发接收消息print(message)group = self.scope["url_route"]["kwargs"].get("group")# #  一对一聊天# if message["text"] == "close":#     self.send("服务端主动关闭连接")#     #  服务端主动关闭连接#     self.close()# self.send(message["text"])# 通知组内的所有客户端,执行xx_oo方法,在此方法中自己可以去定义任意的功能 下边是xx.oo没问题async_to_sync(self.channel_layer.group_send)(group,{"type": "xx.oo","message": message})#  为组内的每个人回复消息def xx_oo(self, event):text = event["message"]["text"]self.send(text)def websocket_disconnect(self, message):# 客户端向服务端断开连接时,自动触发print("连接断开!!")group = self.scope["url_route"]["kwargs"].get("group")async_to_sync(self.channel_layer.group_discard)(group, self.channel_name)raise StopConsumer()

其他无变化,结果展示如下:

在这里插入图片描述
在这里插入图片描述

以上两个属于同一组(num值相同) 所以能相互间接收消息,而下边这个和上边不属于同一组所以接收不到上边的消息

在这里插入图片描述


http://www.ppmy.cn/ops/142129.html

相关文章

力扣.——560. 和为 K 的子数组

给你一个整数数组 nums 和一个整数 k &#xff0c;请你统计并返回 该数组中和为 k 的子数组的个数 。 子数组是数组中元素的连续非空序列。 示例 1&#xff1a; 输入&#xff1a;nums [1,1,1], k 2 输出&#xff1a;2示例 2&#xff1a; 输入&#xff1a;nums [1,2,3], k…

vue依据下拉框选择其余信息

下拉框选择内容后&#xff0c;其余input框与该下拉框相关的内容实时回显,用change加方法 <el-row><el-col :span"12"><el-form-item label"选择站点" prop"resourcesId"><el-select v-model"form.resourcesId" …

【Linux网络】网络基础:传输层UDP/TCP协议(一)

&#x1f4dd;个人主页&#x1f339;&#xff1a;Eternity._ ⏩收录专栏⏪&#xff1a;Linux “ 登神长阶 ” &#x1f339;&#x1f339;期待您的关注 &#x1f339;&#x1f339; ❀ 传输层UDP/TCP协议 &#x1f4d2;端口号&#x1f4dc;UDP协议UDP协议端格式UDP的特点UDP的缓…

【知识科普】工作流引擎activiti详细介绍

工作流引擎activiti 概述一、概述二、主要特点三、核心组件四、应用场景五、数据库表结构六、搭建与使用七、优势与局限性 核心组件介绍一、Activiti Engine&#xff08;流程引擎&#xff09;二、建模组件三、管理组件四、其他核心组件 如何实现审批流流转一、准备工作二、定义…

.NET(C#) 如何配置用户首选项及保存用户设置

最近开发软件&#xff0c;需要将用户设置保存下来以便下次打开后再用&#xff0c;看了半天原来.NET框架自带setting功能。记录如下&#xff1a; 一&#xff0c;“设置” 页面 使用项目设计器的“设置”页指定项目的应用程序设置。 通过应用程序设置&#xff0c;能够为应用程序…

初次使用uniapp编译到微信小程序编辑器页面空白,真机预览有内容

uniapp微信小程序页面结构 首页页面代码 微信小程序模拟器 模拟器页面为空白时查了下&#xff0c;有几个说是“Hbuilder编译的时候应该编译出来一个app.js文件 但是却编译出了App.js”&#xff0c;但是我的小程序结构没问题&#xff0c;并且真机预览没有问题 真机调试 根据defi…

axios请求拦截器和响应拦截器,封装naive-ui的 Loading Bar加载条和useMessage消息提示

接之前的博客设计从0开始边做边学&#xff0c;用vue和python做一个博客&#xff0c;非规范化项目&#xff0c;怎么简单怎么弄&#xff0c;跑的起来有啥毛病解决啥毛病&#xff08;三&#xff09;&#xff0c;目前已经完成了基本的功能demo&#xff0c;但是请求接口不可能每个页…

微服务-01

1.认识微服务 1.1 单体架构 单体架构&#xff08;monolithic structure&#xff09;&#xff1a;顾名思义&#xff0c;整个项目中所有功能模块都在一个工程中开发&#xff1b;项目部署时需要对所有模块一起编译、打包&#xff1b;项目的架构设计、开发模式都非常简单。 当项目…