详解Django3中直接添加Websockets方式
现在Django3.0附带了对ASGI的支持,将Websockets添加到Django应用中不需要任何额外的依赖关系。在本文中,您将学习如何通过扩展默认的ASGI应用程序来使用Django处理Websocket。我们将介绍如何在示例ASGI应用程序中处理Websocket连接,发送和接收数据以及实现业务逻辑。
入门
首先,您需要在计算机上安装Python>=3.6。Django3.0仅与Python3.6及更高版本兼容,因为它使用了async和await关键字。完成Python版本设置后,创建一个项目目录并CD进入。然后,将Django安装在virtualenv内,并在您的项目目录中创建一个新的Django应用:
$mkdirdjango_websockets&&cddjango_websockets $python-mvenvvenv $sourcevenv/bin/activate $pipinstalldjango $django-adminstartprojectwebsocket_app.
看一下Django应用程序的websocket_app目录。您应该看到一个名为asgi.py的文件。其内容如下所示:
importos fromdjango.core.asgiimportget_asgi_application os.environ.setdefault('DJANGO_SETTINGS_MODULE','websocket_app.settings') application=get_asgi_application()
该文件提供了默认的DjangoASGI设置,并公开了一个名为application的ASGI应用程序,可以使用uvicorn或daphne等ASGI服务器运行该应用程序。在进一步介绍之前,让我们看一下ASGI应用程序的结构。
ASGI应用程序结构
ASGI或“异步服务器网关接口”是用于使用Python构建异步Web服务的规范。它是WSGI的精神继承者,WSGI已被Django和Flask等框架使用了很长时间。ASGI使您可以使用Python的本机异步/等待功能来构建支持长期连接的Web服务,例如Websockets和ServerSentEvents。
ASGI应用程序是一个异步函数,它带有3个参数:作用域(当前请求的上下文),接收(一个异步函数,可让您侦听传入的事件)和发送(一个异步函数,可将事件发送至客户端)。
在ASGI应用程序内部,您可以根据范围字典中的值路由请求。例如,您可以通过检查scope[‘type']的值来检查该请求是HTTP请求还是Websocket请求。要侦听来自客户端的数据,您可以等待接收功能。准备好将数据发送到客户端时,可以等待发送功能,然后将要发送给客户端的任何数据传递给客户端。让我们看一下这在示例应用程序中是如何工作的。
创建一个ASGI应用
在我们的asgi.py文件中,我们将使用我们自己的ASGI应用程序包装Django的默认ASGI应用程序功能,以便自己处理Websocket连接。为此,我们需要定义一个名为application的异步函数,该函数需要3个ASGI参数:scope,receive和send。将get_asgi_application调用的结果重命名为django_application,因为我们需要它处理HTTP请求。在我们的应用程序函数内部,我们将检查scope[‘type']的值以确定请求类型。如果请求类型为“http”,则该请求为普通的HTTP请求,我们应该让Django处理它。如果请求类型为“websocket”,那么我们将自己处理逻辑。生成的asgi.py文件应如下所示:
importos fromdjango.core.asgiimportget_asgi_application os.environ.setdefault('DJANGO_SETTINGS_MODULE','websocket_app.settings') django_application=get_asgi_application() asyncdefapplication(scope,receive,send): ifscope['type']=='http': #LetDjangohandleHTTPrequests awaitdjango_application(scope,receive,send) elifscope['type']=='websocket': #We'llhandleWebsocketconnectionshere pass else: raiseNotImplementedError(f"Unknownscopetype{scope['type']}")
现在,我们需要创建一个函数来处理Websocket连接。在与asgi.py文件相同的文件夹中创建一个名为websocket.py的文件,并定义一个名为websocket_application的ASGI应用程序函数,该函数接受3个ASGI参数。接下来,我们将在我们的asgi.py文件中导入websocket_application,并在我们的应用程序函数内部调用它来处理Websocket请求,传入范围,接收和发送参数。它看起来应该像这样:
#asgi.py importos fromdjango.core.asgiimportget_asgi_application fromwebsocket_app.websocketimportwebsocket_application os.environ.setdefault('DJANGO_SETTINGS_MODULE','websocket_app.settings') django_application=get_asgi_application() asyncdefapplication(scope,receive,send): ifscope['type']=='http': awaitdjango_application(scope,receive,send) elifscope['type']=='websocket': awaitwebsocket_application(scope,receive,send) else: raiseNotImplementedError(f"Unknownscopetype{scope['type']}") #websocket.py asyncdefwebsocket_application(scope,receive,send): pass
接下来,让我们为Websocket应用程序实现一些逻辑。我们将监听所有Websocket连接,当客户端发送字符串“ping”时,我们将以字符串“pong!”进行响应。
在websocket_application函数内部,我们将定义一个不确定的循环,该循环将处理Websocket请求,直到关闭连接。在该循环内,我们将等待服务器从客户端收到的任何新事件。然后,我们将根据事件的内容采取行动,并将响应发送给客户端。
首先,让我们处理连接。当新的Websocket客户端连接到服务器时,我们将收到“websocket.connect”事件。为了允许这种连接,我们将发送一个“websocket.accept”事件作为响应。这将完成Websocket握手并与客户端建立持久连接。
当客户端终止其与服务器的连接时,我们还需要处理断开连接事件。为此,我们将监听“websocket.disconnect”事件。当客户端断开连接时,我们将摆脱不确定的循环。
最后,我们需要处理来自客户端的请求。为此,我们将监听“websocket.receive”事件。当我们从客户端收到“websocket.receive”事件时,我们将检查event[‘text']的值是否为“ping”。如果是,我们将发送一个'websocket.send'事件,其文本值为'pong!'。
设置Websocket逻辑后,我们的websocket.py文件应如下所示:
#websocket.py asyncdefwebsocket_application(scope,receive,send): whileTrue: event=awaitreceive() ifevent['type']=='websocket.connect': awaitsend({ 'type':'websocket.accept' }) ifevent['type']=='websocket.disconnect': break ifevent['type']=='websocket.receive': ifevent['text']=='ping': awaitsend({ 'type':'websocket.send', 'text':'pong!' })
测试
现在,我们的ASGI应用程序已设置为处理Websocket连接,并且我们已经实现了Websocket服务器逻辑,让我们对其进行测试。目前,Django开发服务器不使用asgi.py文件,因此您将无法使用./manage.pyrunserver测试连接。相反,您需要使用ASGI服务器(例如uvicorn)运行该应用程序。让我们安装它:
$pipinstalluvicorn
安装uvicorn后,我们可以使用以下命令运行ASGI应用程序:
$uvicornwebsocket_app.asgi:application INFO:Startedserverprocess[25557] INFO:Waitingforapplicationstartup. INFO:ASGI'lifespan'protocolappearsunsupported. INFO:Applicationstartupcomplete. INFO:Uvicornrunningonhttp://127.0.0.1:8000(PressCTRL+Ctoquit)
要测试Websocket连接,请在新选项卡中打开浏览器的开发工具。在控制台中,创建一个名为ws的新Websocket实例,该实例指向ws://localhost:8000/。然后将onmessage处理程序附加到将event.data记录到控制台的ws。最后,调用ws.send('ping')将消息发送到服务器。您应该看到值“pong!”。登录到控制台。
>ws=newWebSocket('ws://localhost:8000/') WebSocket{url:"ws://localhost:8000/",readyState:0,bufferedAmount:0,onopen:null,onerror:null,…} >ws.onmessage=event=>console.log(event.data) event=>console.log(event.data) >ws.send("ping") undefined pong!
恭喜!现在,您知道了如何使用ASGI将Websocket支持添加到Django应用程序中。去用它来制作很棒的东西。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。