社区所有版块导航
Python
python开源   Django   Python   DjangoApp   pycharm  
DATA
docker   Elasticsearch  
aigc
aigc   chatgpt  
WEB开发
linux   MongoDB   Redis   DATABASE   NGINX   其他Web框架   web工具   zookeeper   tornado   NoSql   Bootstrap   js   peewee   Git   bottle   IE   MQ   Jquery  
机器学习
机器学习算法  
Python88.com
反馈   公告   社区推广  
产品
短视频  
印度
印度  
Py学习  »  Django

如何在没有额外依赖项的情况下将Websockets添加到Django应用程序中

Python程序员 • 5 年前 • 670 次点击  

由于Django 3.0已经提供了开箱即用的ASGI支持,因此,将Websockets添加到你的Django应用程序中不需要额外的依赖项。在这篇文章中,你将学习如何通过扩展默认的ASGI应用程序来使用Django处理Websockets。我们将讨论如何处理Websocket连接,发送和接收数据,并在一个示例ASGI应用程序中来实现业务逻辑。


开始


首先,你需要在你的机器上安装Python >= 3.6。Django 3.0只与Python 3.6及以上版本兼容,因为它使用了async 和 await关键字。一旦你设置好你的Python版本之后,创建一个项目目录并使用cd命令切换到其中。然后,在一个virtualenv中安装Django,并在你的项目目录中创建一个新的Django应用程序:



在你的Django应用程序的websocket_app目录看一下,你应该会看到一个名为asgi.py的文件。它的内容看起来将是这样的:



该文件提供了默认的Django ASGI设置,并公开了一个名为application的ASGI应用程序,我们可以使用一个ASGI服务器(比如uvicorn 或 daphne)来运行这个应用程序。在深入讨论之前,让我们先看看ASGI应用程序的结构。


ASGI应用程序结构


ASGI,即异步服务器网关接口,是一个使用Python构建异步web服务的规范。它是WSGI的精神继承者,WSGI已经被像Django和Flask这样的框架使用了很长时间。ASGI允许你使用Python的原生async/await功能来构建支持长连接(如Websockets和服务器发送事件)的web服务。


ASGI应用程序是一个单独的async函数,它接受3个参数:scope(当前请求的上下文)、receive(一个让你监听传入事件的async函数)和send(一个让你向客户端发送事件的async函数)。


在ASGI应用程序内部,你可以根据scope字典中的值来路由请求。例如,你可以通过检查scope['type']的值来检查请求是一个HTTP请求还是一个Websocket请求。要监听来自客户端的数据,你可以await receive函数。当你准备好向客户端发送数据时,你可以await该send函数,并传入任何你想要的数据来将其发送到客户端。让我们在一个示例应用程序中看看这个过程是如何工作的。


创建一个 ASGI 应用程序


在我们asgi.py文件中,我们将用我们自己的ASGI应用程序包装Django的默认ASGI应用程序函数,以便我们自行处理Websocket连接。为此,我们需要定义一个名为application的async函数,它接受三个ASGI参数:scope、receive和send。将get_asgi_application调用的结果重命名为django_application,因为我们需要它来处理HTTP请求。在我们的application函数内部,我们将检查scope['type']的值,以确定请求类型。如果请求类型是“http”,那么这个请求就是一个普通的HTTP请求,我们就应该让Django来处理它。如果这个请求类型是'websocket',那么我们就需要自己处理逻辑。最终的asgi.py文件应该是像这样:




现在我们需要创建一个函数来处理Websocket连接。在与你的asgi.py文件相同的目录中创建一个名为websocket.py的文件,并定义一个名为websocket_application的ASGI应用程序函数,该函数接受3个ASGI参数。接下来,我们将在我们的asgi.py文件中导入websocket_application,并在我们的application函数内部调用它来处理Websocket请求,同时传入scope、receive, 和 send参数。它看起来应该是这样的:



接下来,让我们为我们的Websocket应用程序实现一些逻辑。我们将监听所有Websocket连接,并且当客户端发送字符串“ping”时,我们将用字符串“pong!”进行响应。


在websocket_application函数内部,我们将定义一个无限循环来处理Websocket请求,直到连接关闭。在这个循环中,我们将等待服务器从客户端接收到的任何新事件。然后我们将处理这些事件的内容,并将响应发送给客户端。


首先,让我们来处理连接。当一个新的Websocket客户端连接到服务器时,我们将收到一个'websocket.connect'事件。为了允许这个连接,我们将在响应中发送一个'websocket.accept'。这将完成Websocket握手并与客户端建立一个持久连接。


当一个客户端中断其到服务器的连接时,我们还需要处理断开连接事件。为此,我们将监听'websocket.disconnect'事件。当客户端断开连接时,我们将跳出我们的无限循环。


最后,我们需要处理来自客户端的请求。为此,我们将监听'websocket.receive'事件。当我们收到一个来自客户端的'websocket.receive'事件时,我们将检查并查看event['text']的值是否为'ping'。如果是的话,我们将发送一个'websocket.send'事件,并带有一个text值'pong!'


在设置了Websocket逻辑之后,我们的websocket.py文件看起来应该像这样:



进行测试


现在,我们的ASGI应用程序被设置为处理Websocket连接,并且我们已经实现了我们的Websocket服务器逻辑,让我们来测试一下它。目前,Django开发服务器还没有使用asgi.py文件,因此你无法使用./manage.py runserver来测试你的连接。相反,你需要使用一个ASGI服务器(如uvicorn)来运行该应用程序。我们来安装它:



一旦uvicorn被安装之后,我们可以使用以下命令运行我们的ASGI应用程序:



要测试这个Websocket连接,请在一个新选项卡中打开你的浏览器的开发工具。在控制台中,创建一个名为ws的新Websocket实例,使其指向ws://localhost:8000/。然后向ws附加一个onmessage处理程序,它会将event.data日志记录到控制台。最后,调用ws.send('ping')向服务器发送消息。你应该会看到值“pong!”被日志记录到控制台。



恭喜!现在你知道了如何使用ASGI将Websocket支持添加到你的Django应用程序中。快用它去构建一些很棒的东西吧。


你好,我是Jayden,我喜欢构建应用程序和教别人怎样去构建应用程序。想查看更多有关使用Django、React和GraphQL构建应用程序的文章,请关注我的Twitter或订阅下面的时事通讯。


英文原文:https://jaydenwindle.com/writing/django-websockets-zero-dependencies/ 
译者:忧郁的红秋裤

Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/54992
 
670 次点击