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

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

改动点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 = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_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/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': BASE_DIR / 'db.sqlite3',
    }
}


# Password validation
# https://docs.djangoproject.com/en/4.2/ref/settings/#auth-password-validators

AUTH_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 = True

USE_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-field

DEFAULT_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_sync

class ChatConsumer(WebsocketConsumer):  # 继承WebsocketConsumer
   def 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值相同) 所以能相互间接收消息,而下边这个和上边不属于同一组所以接收不到上边的消息

在这里插入图片描述

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

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

相关文章

Keil-MDK开发环境编译后axf自动转换bin格式文件

编译选项添加如下&#xff0c;调用fromelf工具自动完成转换&#xff1a; fromelf --bin -o "$LL.bin" "#L"

如何快速搭建若依管理系统?

1、下载若依管理系统前后端分离版代码至本地&#xff08;当前版本为RuoYi v3.8.8&#xff09;&#xff1a; RuoYi-Vue: &#x1f389; 基于SpringBoot&#xff0c;Spring Security&#xff0c;JWT&#xff0c;Vue & Element 的前后端分离权限管理系统&#xff0c;同时提供…

【JavaEE】网络(1)

&#x1f435;本篇文章开始讲解计算机网络相关的知识 一、基础概念 1.1 局域网和广域网 局域网→Local Area Network→简称LAN&#xff0c;局域网是局部组建的一种私有网络&#xff0c;局域网内的主机之间可以进行网络通信&#xff0c;局域网和局域网之间在没有连接的情况不能…

网络应用技术 实验八:防火墙实现访问控制(华为ensp)

目录 一、实验简介 二、实验目的 三、实验需求 四、实验拓扑 五、实验步骤 1、设计全网 IP 地址 2、设计防火墙安全策略 3、在 eNSP 中部署园区网 4、配置用户主机地址 5、配置网络设备 配置交换机SW-1~SW-5 配置路由交换机RS-1~RS-5 配置路由器R-1~R-3 6、配置仿…

day11 性能测试(4)——Jmeter使用(黑马的完结,课程不全)直连数据库+逻辑控制器+定时器

【没有所谓的运气&#x1f36c;&#xff0c;只有绝对的努力✊】 目录 1、复习 1.1 断言&#xff08;3种&#xff09; 1.2 关联&#xff08;3种&#xff09; 1.3 录制脚本 2、Jmeter直连数据库 2.1 直连数据库——使用场景 2.2 直连数据库——操作步骤 2.2.1 案例1&…

Modelscope AgentFabric: 开放可定制的AI智能体构建框架

目录 git clone https://github.com/modelscope/modelscope-agent.git cd modelscope-agent && pip install -r requirements.txt && pip install -r apps/agentfabric/requirements.txtexport PYTHONPATH$PYTHONPATH:/home/ubuntu/users/lilingfei/modelscop…

CSS|08 浮动清除浮动

浮动 需求: 能够实现让多个元素排在同一行&#xff0c;并且给这些元素设置宽度与高度! 让多个元素排在同一行:行内元素的特性 给这些元素设置宽高:块级元素的特性 在标准文档流中的元素只有两种:块级元素和行内元素。如果想让一些元素既要有块级元素的特点也要有行内元素的特…

[Pro Git#3] 远程仓库 | ssh key | .gitignore配置

目录 1. 分布式版本控制系统的概念 2. 实际使用中的“中央服务器” 3. 远程仓库的理解 4. 新建远程仓库 5. 克隆远程仓库 6. 设置SSH Key 实验 一、多用户协作与公钥管理 二、克隆后的本地与远程分支对应 三、向远程仓库推送 四、拉取远程仓库更新 五、配置Git忽略…

【uni-app】App与webview双向实时通信

【uni-app】App与webview双向实时通信 在 Uniapp 中&#xff0c;App 与 里面嵌入的 webview 进行双向的实时通信 vue2 &#xff0c; 模拟器 主要分为两部分 webview 向 app 发送信息 app 向 webview 发送信息 以下是实现方式&#xff0c;用一个例子来说明 &#xff08;文…

微信小程序处理交易投诉管理,支持多小程序

大家好&#xff0c;我是小悟 1、问题背景 玩过微信小程序生态的&#xff0c;或许就有这种感受&#xff0c;如果收到投诉单&#xff0c;不会及时通知到手机端&#xff0c;而是每天早上10:00向小程序的管理员及运营者推送通知。通知内容为截至前一天24时该小程序账号内待处理的交…

AIGC-------AI生成内容如何赋能AR和VR体验?

AI生成内容如何赋能AR和VR体验 引言 增强现实&#xff08;AR&#xff09;和虚拟现实&#xff08;VR&#xff09;技术近年来蓬勃发展&#xff0c;为用户提供了沉浸式的体验。这些技术已经广泛应用于游戏、教育、医疗、建筑等领域。然而&#xff0c;AR和VR体验的质量与内容的丰富…

zotero安装教程(包括茉莉花插件)

zotero安装教程&#xff08;包括茉莉花插件&#xff09; zotero下载(windows)1-安装 Zotero2-安装 Zotero Connector3-安装浏览器插件--jasminum茉莉花功能&#xff1a;插件下载地址&#xff1a;[https://github.com/search?qjasminum&typerepositories](https://github.c…

M|可可西里

title: 可可西里 time: 2024-12-15 周日 rating: 8.5 豆瓣: 8.9 上映时间: “2004” 类型: M剧情犯罪 导演: 陆川 Chuan Lu 主演: 多布杰 Duobujie张垒 Lei Zhang 国家/地区: 中国大陆 片长/分钟: 90分钟 M&#xff5c;可可西里 粗砺的苍凉&#xff0c;沉默的悲壮。…

ArcGIS教程(007):制作中国行政区划图

文章目录 000:数据准备001:利用地理数据制作中国行政区划图000:数据准备 通过网盘分享的文件:ArcGIS教程(007):中国行政区划图教程练习数据.zip 链接: https://pan.baidu.com/s/1nMiRYD-dbv2S0DoeQzR87g?pwd=3535 提取码: 3535001:利用地理数据制作中国行政区划图 ne_…

KeepAlive与RouterView缓存

参考 vue动态组件&#xff1c;Component&#xff1e;与&#xff1c;KeepAlive&#xff1e; KeepAlive官网介绍 缓存之keep-alive的理解和应用 Vue3Vite KeepAlive页面缓存问题 vue多级菜单(路由)导致缓存(keep-alive)失效 vue3 router-view keeperalive对于同一路径但路径…

类与对象以及ES6的继承

认识class定义类 类的声明用的比较多 类与构造函数的异同 类的构造函数 类的实例方法 类的访问器方法 在类里面写拦截方法 类的静态方法 通过类名直接访问 es6类的继承-extends super关键字 子类可以重写父类方法包括父类的静态方法也可以继承父类的静态方法 babel可以将新的代…

AI监控赋能健身馆与游泳馆全方位守护,提升安全效率

一、AI视频监控技术的崛起 随着人工智能技术的不断发展&#xff0c;AI视频监控正成为各行业保障安全、提升效率的关键工具。相比传统监控系统&#xff0c;AI技术赋予监控系统实时分析、智能识别和精准预警的能力&#xff0c;让“被动监视”转变为“主动防控”。 二、AI监控应用…

嵌入式学习(18)-stm32F407串口接收空闲中断+DMA

一、概述 在一些一次性接收大批量数据的引用场合&#xff0c;如果使用接收中断会频繁的进入接收中断影响代码的运行效率。为了解决这个问题可以使用串口的空闲中断DMA实现。 二、应用 在网上招了一些例程在STM32F407的平台上都没有跑通会出现各种异常&#xff0c;主要原因还…

2024.12.15CISCN长城杯铁人三项赛

WEB Safe_Proxy 刚开始比赛看到题目名字里面有Proxy 就先来做这个了(在最近的比赛中见到的proxy题比较多) 题目进入之后给了源码 源码 from flask import Flask, request, render_template_string import socket import threading import htmlapp Flask(__name__)app.rout…

【Linux服务器nginx前端部署详解】ubantu22.04,前端Vue项目dist打包

本文主要讲一下在Linux系统环境下&#xff08;以ubantu22.04为例&#xff09;&#xff0c;如何用nginx部署前端Vue项目打包的dist静态资源。有些具体的命令就不展开讲了&#xff0c;可以自行查看其他博主的文章&#xff0c;我主要讲整体的步骤和思路。 一、ubantu系统安装ngin…