Django中的实时通信:WebSockets与异步视图的结合

👽发现宝藏

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。【点击进入巨牛的人工智能学习网站】。

在现代Web应用程序中,实时通信已经成为了必不可少的功能之一。无论是在线聊天、实时数据更新还是实时通知,都需要通过实时通信技术来实现。Django作为一个强大的Web框架,提供了许多工具来构建各种类型的Web应用程序,但是在实时通信方面,传统的请求-响应模式显然无法满足需求。在这篇文章中,我们将探讨如何利用Django中的WebSockets和异步视图来实现实时通信功能。

WebSockets简介

WebSockets是一种在单个TCP连接上提供全双工通信的协议。与HTTP请求-响应模式不同,WebSockets允许服务器和客户端之间进行持续的双向通信,从而实现了实时性。在Django中,我们可以使用第三方库django-channels来实现WebSocket的支持。

image-20240330143213129

异步视图

Django 3.1引入了异步视图的支持,使得我们可以编写异步处理请求的视图函数。这对于处理长时间运行的任务或需要等待外部资源响应的请求非常有用。

结合WebSockets与异步视图

下面我们将通过一个案例来演示如何在Django中结合WebSockets和异步视图来实现实时通信功能。假设我们正在开发一个简单的实时聊天应用。

安装依赖

首先,我们需要安装django-channels库:

pip install channels

配置项目

在项目的settings.py中,添加channels应用:

INSTALLED_APPS = [
    ...
    'channels',
    ...
]

然后,创建一个名为routing.py的新文件,在其中定义WebSocket路由:

# routing.py

from channels.routing import ProtocolTypeRouter, URLRouter
from channels.auth import AuthMiddlewareStack
from django.urls import path
from myapp.consumers import ChatConsumer

websocket_urlpatterns = [
    path('ws/chat/', ChatConsumer.as_asgi()),
]

application = ProtocolTypeRouter({
    'websocket': AuthMiddlewareStack(
        URLRouter(
            websocket_urlpatterns
        )
    ),
})

创建Consumer

接下来,我们创建一个消费者(Consumer)来处理WebSocket连接:

# consumers.py

import json
from channels.generic.websocket import AsyncWebsocketConsumer

class ChatConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_name = 'chat_room'
        self.room_group_name = f'chat_{self.room_name}'

        # 加入聊天室群组
        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )

        await self.accept()

    async def disconnect(self, close_code):
        # 离开聊天室群组
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']

        # 发送消息到聊天室群组
        await self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': message
            }
        )

    async def chat_message(self, event):
        message = event['message']

        # 发送消息给WebSocket连接
        await self.send(text_data=json.dumps({
            'message': message
        }))

编写前端代码

在前端页面中,我们需要使用JavaScript来连接WebSocket并处理消息的发送和接收:

// chat.js

const chatSocket = new WebSocket('ws://localhost:8000/ws/chat/');

chatSocket.onmessage = function(e) {
    const data = JSON.parse(e.data);
    const message = data['message'];
    // 处理收到的消息
    console.log(message);
};

chatSocket.onclose = function(e) {
    console.error('Chat socket closed unexpectedly');
};

document.querySelector('#chat-message-input').addEventListener('keypress', function(e) {
    if (e.key === 'Enter') {
        const messageInputDom = document.querySelector('#chat-message-input');
        const message = messageInputDom.value;
        chatSocket.send(JSON.stringify({
            'message': message
        }));
        messageInputDom.value = '';
    }
});

image-20240330143127425

集成到模板

最后,我们在Django模板中集成JavaScript代码:

<!-- chat.html -->

<!DOCTYPE html>
<html>
<head>
    <title>Chat</title>
</head>
<body>
    <textarea id="chat-message-input"></textarea>
    <script src="{% static 'chat.js' %}"></script>
</body>
</html>

引入异步视图

在Django 3.1之前,视图函数都是同步执行的,这意味着一个视图函数中的代码会一直执行直到返回一个HTTP响应给客户端。然而,有些任务可能是耗时的,比如调用外部API或者执行复杂的计算。在这种情况下,同步视图会阻塞整个应用程序,导致性能下降。

为了解决这个问题,Django引入了异步视图,它们使用Python的asyncawait语法来支持异步编程模式。异步视图允许在处理请求时挂起执行,等待IO操作完成而不会阻塞整个应用程序。

结合WebSockets与异步视图的优势

结合WebSockets与异步视图可以使得实时通信应用具备更高的性能和可扩展性。当有大量连接同时进行通信时,异步视图可以有效地管理这些连接,而不会因为一个连接的阻塞而影响其他连接的处理。这种方式下,应用程序能够更好地应对高并发情况,保持稳定性和高效性。

image-20240330143335659

完善实时聊天应用

除了上述示例中的基本聊天功能之外,我们还可以对实时聊天应用进行一些扩展,比如:

  1. 用户认证:在连接WebSocket时进行用户认证,确保只有已登录的用户可以进入聊天室。
  2. 聊天室管理:创建多个聊天室,并允许用户选择加入不同的聊天室。
  3. 消息存储:将聊天记录保存到数据库中,以便用户在断线重连后可以查看历史消息。
  4. 消息通知:实现消息通知功能,当用户收到新消息时,通过浏览器通知或邮件提醒用户。
  5. 实时在线用户列表:显示当前在线用户列表,并在用户进入或离开聊天室时实时更新。

实时地理位置共享

假设我们正在开发一个实时地理位置共享应用,用户可以在地图上实时看到其他用户的位置。以下是一个简单的示例代码:

后端代码
# consumers.py

import json
from channels.generic.websocket import AsyncWebsocketConsumer

class LocationConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_name = 'location_room'
        self.room_group_name = f'location_{self.room_name}'

        # 加入地理位置共享房间
        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )

        await self.accept()

    async def disconnect(self, close_code):
        # 离开地理位置共享房间
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        latitude = text_data_json['latitude']
        longitude = text_data_json['longitude']

        # 发送位置信息到地理位置共享房间
        await self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'location_message',
                'latitude': latitude,
                'longitude': longitude
            }
        )

    async def location_message(self, event):
        latitude = event['latitude']
        longitude = event['longitude']

        # 发送位置信息给WebSocket连接
        await self.send(text_data=json.dumps({
            'latitude': latitude,
            'longitude': longitude
        }))
前端代码
// location.js

const locationSocket = new WebSocket('ws://localhost:8000/ws/location/');

locationSocket.onmessage = function(e) {
    const data = JSON.parse(e.data);
    const latitude = data['latitude'];
    const longitude = data['longitude'];
    // 在地图上显示用户位置
    updateMap(latitude, longitude);
};

locationSocket.onclose = function(e) {
    console.error('Location socket closed unexpectedly');
};

function sendLocation(latitude, longitude) {
    locationSocket.send(JSON.stringify({
        'latitude': latitude,
        'longitude': longitude
    }));
}

在这个示例中,用户通过前端界面在地图上选择或移动位置,然后通过WebSocket发送位置信息到服务器。服务器接收到位置信息后,将其广播给所有连接的用户,前端界面接收到位置信息后,在地图上实时更新其他用户的位置。

这样的实时地理位置共享功能可以应用在社交应用、实时导航应用等场景中,为用户提供更好的交互体验。

实时数据可视化

假设我们有一个数据监控系统,需要实时展示各种传感器的数据。以下是一个简单的示例代码:

后端代码
# consumers.py

import json
from channels.generic.websocket import AsyncWebsocketConsumer

class SensorDataConsumer(AsyncWebsocketConsumer):
    async def connect(self):
        self.room_name = 'sensor_data_room'
        self.room_group_name = f'sensor_data_{self.room_name}'

        # 加入传感器数据共享房间
        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )

        await self.accept()

    async def disconnect(self, close_code):
        # 离开传感器数据共享房间
        await self.channel_layer.group_discard(
            self.room_group_name,
            self.channel_name
        )

    async def receive(self, text_data):
        text_data_json = json.loads(text_data)
        sensor_id = text_data_json['sensor_id']
        sensor_value = text_data_json['sensor_value']

        # 发送传感器数据到传感器数据共享房间
        await self.channel_layer.group_send(
            self.room_group_name,
            {
                'type': 'sensor_data_message',
                'sensor_id': sensor_id,
                'sensor_value': sensor_value
            }
        )

    async def sensor_data_message(self, event):
        sensor_id = event['sensor_id']
        sensor_value = event['sensor_value']

        # 发送传感器数据给WebSocket连接
        await self.send(text_data=json.dumps({
            'sensor_id': sensor_id,
            'sensor_value': sensor_value
        }))
前端代码
// sensor_data.js

const sensorDataSocket = new WebSocket('ws://localhost:8000/ws/sensor_data/');

sensorDataSocket.onmessage = function(e) {
    const data = JSON.parse(e.data);
    const sensorId = data['sensor_id'];
    const sensorValue = data['sensor_value'];
    // 更新传感器数据图表
    updateChart(sensorId, sensorValue);
};

sensorDataSocket.onclose = function(e) {
    console.error('Sensor data socket closed unexpectedly');
};

function sendSensorData(sensorId, sensorValue) {
    sensorDataSocket.send(JSON.stringify({
        'sensor_id': sensorId,
        'sensor_value': sensorValue
    }));
}

在这个示例中,传感器设备通过WebSocket将实时数据发送到服务器,服务器接收到数据后将其广播给所有连接的用户,前端界面接收到数据后,使用JavaScript图表库将实时数据实时展示在图表中。

这样的实时数据可视化功能可以应用在数据监控、实时分析等场景中,为用户提供实时的数据展示和监控功能。

image-20240330143414954

高级功能和进阶应用

除了基本的实时聊天功能之外,结合WebSockets和异步视图还可以实现一系列高级功能和进阶应用。以下是一些示例:

1. 实时地理位置共享

利用WebSocket和异步视图,可以实现用户之间实时的地理位置共享。当用户移动时,前端应用可以将用户的位置信息发送到服务器,服务器再将这些信息广播给其他用户。这种功能在社交应用、地图导航应用等场景中非常有用。

2. 实时数据可视化

在数据分析和监控领域,实时数据可视化是一项重要的任务。通过WebSocket和异步视图,可以实时将数据传输到前端,并利用JavaScript图表库(如Highcharts、Chart.js等)实时展示数据变化趋势、实时监控系统状态等。

3. 在线协作编辑

利用WebSocket和异步视图,可以实现多人在线协作编辑功能,类似于Google Docs。当一个用户编辑文档时,其余用户可以实时看到编辑内容的变化,从而实现多人实时协作编辑。

4. 实时游戏

实时游戏对于实时通信的需求非常高。结合WebSocket和异步视图,可以实现实时的多人在线游戏,比如棋牌游戏、实时战略游戏等,提供流畅的游戏体验。

5. 实时搜索和过滤

在网站和应用中,用户可能需要实时搜索和过滤数据。通过WebSocket和异步视图,可以实时向服务器发送搜索关键词或过滤条件,并实时获取服务器返回的搜索结果或过滤后的数据,从而提高用户体验。

6. 实时投票和问卷调查

在线投票和问卷调查通常需要实时获取投票结果或问卷填写情况。结合WebSocket和异步视图,可以实时更新投票结果图表或问卷统计数据,让用户实时了解当前的投票情况或问卷填写进度。

总结

本文介绍了如何利用Django中的WebSockets和异步视图来实现实时通信功能。我们首先了解了WebSockets的基本概念和工作原理,以及Django中使用django-channels库来支持WebSockets的方法。接着,我们深入探讨了异步视图的概念和用法,以及如何结合WebSockets和异步视图来实现实时通信功能。

通过一个简单的实时聊天应用的示例,我们演示了如何创建WebSocket消费者(Consumer)来处理WebSocket连接,并利用异步视图来处理WebSocket连接中的事件。我们还介绍了如何在前端页面中使用JavaScript来连接WebSocket,并实时处理接收到的消息。

随后,我们进一步探讨了结合WebSockets和异步视图的优势,并提供了一系列高级功能和进阶应用的示例,包括实时地理位置共享、实时数据可视化等。这些功能和应用可以为开发者提供更多的创新和可能性,从而满足不同场景下的实时通信需求。

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

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

相关文章

UKP3D,出轴 /平面图时,选项中出图比例,绘图比例,打印比例的区别

Q:用户问&#xff0c;轴测图正常&#xff0c;平面图位置不对&#xff0c;这个也需要在xml里面调整吗&#xff1f; 在此&#xff0c;先不回复上述问题&#xff0c;而是解释在出图规则里的选项意思。 1.图框比例&#xff1a;图框比例1:100&#xff0c;例如选中的图幅是A0横式&…

现代图形API综合比较:Vulkan | DirectX | Metal | WebGPU

Vulkan、DirectX、Metal 和 WebGPU 等低级图形 API 正在融合为类似于当前 GPU 构建方式的模型。 图形处理单元 (GPU) 是异步计算单元&#xff0c;可以处理大量数据&#xff0c;例如复杂的网格几何形状、图像纹理、输出帧缓冲区、变换矩阵或你想要计算的任何数据。 NSDT工具推荐…

TFS(淘宝分布式存储引擎

TFS&#xff08;淘宝分布式存储引擎&#xff09; 什么是TFS&#xff1f; ​ 根据淘宝2016年的数据分析&#xff0c;淘宝卖家已经达到900多万&#xff0c;有上十亿的商品。每一个商品有包括大量的图片和文字(平均&#xff1a;15k)&#xff0c;粗略估计下&#xff0c;数据所占的…

编译一个基于debian/ubuntu,centos,arhlinux第三方系统

目录 前言 准备工作 下载linux源码进行编译 linux源码下载 网站 问题 解决办法 编译 可能会遇到的问题 chroot下载debian环境 进入虚拟环境 把chroot的根目录文件打包为.gz文件 编译init文件&#xff08;用于系统启动时的一系列引导&#xff09; 给予文件夹权限 …

pip下载包opencv出错(报错failed building wheel for opencv-python解决方法)

文章目录 1 报错2 原因3 解决方法参考 1 报错 ERROR: Could not build wheels for opencv-python, which is required to install pypr2 原因 版本不兼容的问题,当使用pip install opencv-python命令安装的是最新版本&#xff0c;当前python版本不支持。需要安装当前版本pyth…

34. 【Android教程】菜单:Menu

作为 Android 用户&#xff0c;你一定见过类似这样的页面&#xff1a; 它就是我们今天的主角——菜单&#xff0c;它的使用场景和作用不用多说&#xff0c;几乎每个 App 都会用到它&#xff0c;今天我们就一起来看看 Android 提供的几种菜单类型及用法。 1. 菜单的几种类型 根…

✌粤嵌—2024/4/12—插入区间✌

代码实现&#xff1a; 解题思路&#xff1a;先将数组 newInterval 插入到数组 intervals 的末尾&#xff0c;再转换成合并区间 /*** Return an array of arrays of size *returnSize.* The sizes of the arrays are returned as *returnColumnSizes array.* Note: Both returne…

LabVIEW专栏六、LabVIEW项目

一、梗概 项目&#xff1a;后缀是.lvproj&#xff0c;在实际开发的过程中&#xff0c;一般是要用LabVIEW中的项目来管理代码&#xff0c;也就是说相关的VI或者外部文件&#xff0c;都要放在项目中来管理。 在LabVIEW项目中&#xff0c;是一个互相依赖的整体&#xff0c;可以包…

319_C++_使用QT自定义的对话框,既能选择文件也能选择文件夹,为什么使用QListView和QTreeView来达成目的?

解析 1: 在 Qt 中,QFileDialog::setOption 方法用于设置文件对话框的一些选项,以改变其行为或外观。QFileDialog::DontUseNativeDialog 是这些选项之一,当设置为 true 时,它会告诉 QFileDialog 不要使用操作系统提供的原生文件对话框,而是使用 Qt 自己实现的对话框样式。…

js作业微博发言与轮播(有瑕疵)

微博 <!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0"><meta http-equiv"X-UA-Compatible" content&q…

H5 台球猜位置小游戏

刷到抖音有人这样玩&#xff0c;就写了一个这样的小游戏练习一下H5的知识点。 小游戏预览 w(&#xff9f;Д&#xff9f;)w 不开挂越急越完成不了&#xff0c;&#x1f47f;确认15次也没全对… 知识点 获取坐标位置的DOM元素&#xff0c;感觉应该是新的吧&#xff0c;以前的…

Aws Nat Gateway

要点 NAT网关要能访问外网&#xff0c;所以需要部署在有互联网网关的Public子网中。 关键&#xff1a; NAT网关创建是选择子网&#xff0c;一定要选择公有子网&#xff08;有互联网网关子网&#xff09; 特别注意&#xff1a; 新建nat网关的时候&#xff0c;选择的子网一定…

jeecgflow之camunda工作流-并行网关

引言 书接上回&#xff0c;继续三国流程系列教程。 本文主要讲解并行网关。 并行网关允许流程中的多个任务同时执行&#xff0c;从而提高流程的执行效率。 并行网关会忽视序列流上的条件设置。 并行网关分为两部分。 Fork: 用于任务开始 Join:用于任务结束 体验文章demo演示站…

【Camera Framework笔记】二、Camera Native Framework架构①

一、总体架构&#xff1a; service -> opencamera -> client&#xff08;api1/api2&#xff09; -> device3&#xff08;hal3&#xff09; | | &#xff08;不opencamera…

kubernetes学习

1、应用部署方式演变 2、kubernetes介绍 3、kubernetes组件 4、kubernetes概念 5、环境搭建-环境规划 集群类型&#xff1a; 安装方式&#xff1a; 主机规划&#xff1a; 6、环境搭建-主机安装 使用虚拟机安装三台centos7&#xff08;一主二从&#xff09;&#xff0c;然后在…

相机摄影入门技巧,数码摄影技巧大全

一、资料前言 本套数码相机摄影资料&#xff0c;大小1.08G&#xff0c;共有42个文件。 二、资料目录 《aking人像摄影技巧分享》.pdf 《Nikon.D90数码单反摄影技巧大全》FUN视觉.全彩版.pdf 《不可不学的摄影技巧》.pdf 《常用场景摄影》.pdf 《单反数码摄影专家技法》.…

ASP.NET基于Web的招投标系统的设计与实现

摘 要 招标拍卖的历史悠久&#xff0c;在近两千年的发展历程中&#xff0c;人们对拍卖的理论和技术做了大量的探讨。随着计算机网络技术的迅猛发展和日益成熟&#xff0c;为了提高招投标及采购工作的效率&#xff0c;为廉政建设和防止腐败提供技术保障&#xff0c;传统的拍…

JS -关于对象相关介绍

在JS中&#xff0c;除去基本的数据类型&#xff0c;还有包含对象这种复合数据类型&#xff0c;他可以储存多个键值对&#xff0c;并且每个键都是唯一的&#xff0c;并且在对象中可以包含各种数据类型的值&#xff0c;包括其他对象&#xff0c;数组&#xff0c;函数等。对象是Ja…

[AI]-(第0期):认知深度学习

深度学习是一种人工智能&#xff08;AI&#xff09;方法&#xff0c;用于教计算机以受人脑启发的方式处理数据。 深度学习模型可以识别图片、文本、声音和其他数据中的复杂模式&#xff0c;从而生成准确的见解和预测。 您可以使用深度学习方法自动执行通常需要人工智能完成的…

linux 基础命令docker及防火墙iptables详解

应用场景&#xff1a; web应用自动打包和发布 自动化测试&#xff0c;持续集成、发布 在服务环境中部署后台应用 搭建paaS平台 安装应用 apt install docker.io#kali中 配置docker源&#xff0c;文件位置/etc/docker/daemon.json { "registry-mirrors": [ "h…
最新文章