Py学习  »  Django

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

Python程序员 • 4 年前 • 358 次点击  

由于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
 
358 次点击