此前博主曾经写过一篇博文,介绍了Django3.0的新特性,其中最主要的就是加入对ASGI的支持,实现全双工的异步通讯。
(更多Django的教程和博客,能够访问个人官网http://www.liujiangblog.com,或者收藏个人微信公众号‘Django之家
’。)css
2019年12月2日,Django终于正式发布了3.0版本。怀着无比的期待,咱们来尝试一下吧!html
(附ASGI官方文档地址:https://asgi.readthedocs.io/en/latest/extensions.html)python
利用Pycharm的方便,直接经过virtualenv建立虚拟环境,并安装Django3.0。web
打开控制台,看看都安装了哪些库:sql
(venv) D:\work\for_test\django3>pip list Package Version ------ asgiref 3.2.3 Django 3.0 pip 10.0.1 pytz 2019.3 setuptools 39.1.0 sqlparse 0.3.0
除了pytz和sqlparse,又自动安装了asgiref。django
asigref由Django软件基金会开发和维护,是一个Django生态中的库。浏览器
先启动一下服务器,看看Django是否正常运行:服务器
没毛病,能够把服务器关了!微信
毕竟是很是重要和复杂的新特性,先到官网取取经,看看文档怎么写的。websocket
找了一圈,What?就这么点东西?
先康康吧。
(更多Django的教程和博客,能够访问个人官网http://www.liujiangblog.com,或者收藏个人微信公众号‘Django之家
’。)
How to deploy with ASGI As well as WSGI, Django also supports deploying on ASGI, the emerging Python standard for asynchronous web servers and applications. Django’s startproject management command sets up a default ASGI configuration for you, which you can tweak as needed for your project, and direct any ASGI-compliant application server to use. Django includes getting-started documentation for the following ASGI servers: How to use Django with Daphne How to use Django with Uvicorn The application object Like WSGI, ASGI has you supply an application callable which the application server uses to communicate with your code. It’s commonly provided as an object named application in a Python module accessible to the server. The startproject command creates a file <project_name>/asgi.py that contains such an application callable. It’s not used by the development server (runserver), but can be used by any ASGI server either in development or in production. ASGI servers usually take the path to the application callable as a string; for most Django projects, this will look like myproject.asgi:application. Warning While Django’s default ASGI handler will run all your code in a synchronous thread, if you choose to run your own async handler you must be aware of async-safety. Do not call blocking synchronous functions or libraries in any async code. Django prevents you from doing this with the parts of Django that are not async-safe, but the same may not be true of third-party apps or Python libraries. Configuring the settings module When the ASGI server loads your application, Django needs to import the settings module — that’s where your entire application is defined. Django uses the DJANGO_SETTINGS_MODULE environment variable to locate the appropriate settings module. It must contain the dotted path to the settings module. You can use a different value for development and production; it all depends on how you organize your settings. If this variable isn’t set, the default asgi.py sets it to mysite.settings, where mysite is the name of your project. Applying ASGI middleware To apply ASGI middleware, or to embed Django in another ASGI application, you can wrap Django’s application object in the asgi.py file. For example: from some_asgi_library import AmazingMiddleware application = AmazingMiddleware(application)
文档短小无力,内容稀少!
总结就如下几点:
myproject.asgi:application
文件,是ASGI通讯的接口,Django默认自带DJANGO_SETTINGS_MODULE
环境,或者使用默认的your_project.settings
再简单粗暴点,全文的意思是,你须要安装Daphne,而后调用Django的application来启动ASGI服务器。
好吧,咱们看看Daphne,点击Django给的链接,跳转到相关页面,内容更少:
How to use Django with Daphne Daphne is a pure-Python ASGI server for UNIX, maintained by members of the Django project. It acts as the reference server for ASGI. Installing Daphne You can install Daphne with pip: python -m pip install daphne Running Django in Daphne When Daphne is installed, a daphne command is available which starts the Daphne server process. At its simplest, Daphne needs to be called with the location of a module containing an ASGI application object, followed by what the application is called (separated by a colon). For a typical Django project, invoking Daphne would look like: daphne myproject.asgi:application This will start one process listening on 127.0.0.1:8000. It requires that your project be on the Python path; to ensure that run this command from the same directory as your manage.py file.
翻译过来就是:
daphne myproject.asgi:application
命令,启动ASGI服务器我们照作!
经过pip install daphne
便可安装最新版本的daphne:
Collecting pycparser (from cffi!=1.11.3,>=1.8->cryptography>=2.7->autobahn>=0.18->daphne) Installing collected packages: idna, hyperlink, zope.interface, attrs, six, Automat, constantly, PyHamcrest, incremental, pycparser, cffi, cry ptography, pyopenssl, pyasn1, pyasn1-modules, service-identity, twisted, txaio, autobahn, daphne Successfully installed Automat-0.8.0 PyHamcrest-1.9.0 attrs-19.3.0 autobahn-19.11.1 cffi-1.13.2 constantly-15.1.0 cryptography-2.8 daphne-2.4. 0 hyperlink-19.0.0 idna-2.8 incremental-17.5.0 pyasn1-0.4.8 pyasn1-modules-0.2.7 pycparser-2.19 pyopenssl-19.1.0 service-identity-18.1.0 six-1 .13.0 twisted-19.10.0 txaio-18.8.1 zope.interface-4.7.1
为了安装daphne,须要额外安装这么多依赖包!咱们再pip list看一下:
(venv) D:\work\for_test\django3>pip list Package Version ---------------- ------- asgiref 3.2.3 attrs 19.3.0 autobahn 19.11.1 Automat 0.8.0 cffi 1.13.2 constantly 15.1.0 cryptography 2.8 daphne 2.4.0 Django 3.0 hyperlink 19.0.0 idna 2.8 incremental 17.5.0 pip 10.0.1 pyasn1 0.4.8 pyasn1-modules 0.2.7 pycparser 2.19 PyHamcrest 1.9.0 pyOpenSSL 19.1.0 pytz 2019.3 service-identity 18.1.0 setuptools 39.1.0 six 1.13.0 sqlparse 0.3.0 Twisted 19.10.0 txaio 18.8.1 zope.interface 4.7.1
无论了,就当没看见。
安装成功后,咱们会得到一个daphne可执行命令,下面咱们来启动服务器吧。
执行daphne django3.asgi:application
命令。(将其中的django3换成你的工程名字,在manage.py文件所在的路径下执行)
(venv) D:\work\for_test\django3>daphne django3.asgi:application 2019-12-04 10:20:07,637 INFO Starting server at tcp:port=8000:interface=127.0.0.1 2019-12-04 10:20:07,637 INFO HTTP/2 support not enabled (install the http2 and tls Twisted extras) 2019-12-04 10:20:07,637 INFO Configuring endpoint tcp:port=8000:interface=127.0.0.1 2019-12-04 10:20:07,637 INFO Listening on TCP address 127.0.0.1:8000
固然,咱们也是能够指定ip和port等参数的,详细请学习daphne文档https://pypi.org/project/daphne/
读一下人家的启动信息:
Nice,经过浏览器来访问一下吧!
依然是熟悉的白底火箭图!图片我就不贴了,看起来没问题。
但是,这是基于HTTP的同步通讯,还不是异步请求!让咱们尝试一下websocket吧!
浏览器中按F12进入‘坦克模式’,再进入console控制台,尝试发送一个Websocket请求:
忽视前面的css问题,重点在于这个ws请求,竟然没法创建链接!返回状态码500,也就是服务器错误!
再看看Pycharm后台的信息:
127.0.0.1:5991 - - [04/Dec/2019:10:30:05] "WSCONNECTING /" - - 2019-12-04 10:30:05,246 ERROR Exception inside application: Django can only handle ASGI/HTTP connections, not websocket. File "d:\work\for_test\django3\venv\lib\site-packages\daphne\cli.py", line 30, in asgi await self.app(scope, receive, send) File "d:\work\for_test\django3\venv\lib\site-packages\django\core\handlers\asgi.py", line 146, in __call__ % scope['type'] Django can only handle ASGI/HTTP connections, not websocket. 127.0.0.1:5991 - - [04/Dec/2019:10:30:05] "WSDISCONNECT /" - -
重点在这句Django can only handle ASGI/HTTP connections, not websocket.
什么?Django不支持Websocket?说好的ASGI,说好的全双工异步通讯呢?
难道是我哪里搞错了?不行,我得看看源码去!
一路点点点,翻了个遍,发现Django3.0与以前的2.2关于ASGI的区别就是多了下面两个文件:
django.core.asgi
很简单,一看就懂,很少说:
import django from django.core.handlers.asgi import ASGIHandler def get_asgi_application(): django.setup(set_prefix=False) return ASGIHandler()
关键是django.core.handlers.asgi
这个文件,不到300行,总共就2个类,代码就不贴了:
让咱们看看它的其中一段代码:
# Serve only HTTP connections. # FIXME: Allow to override this. if scope['type'] != 'http': raise ValueError( 'Django can only handle ASGI/HTTP connections, not %s.' % scope['type'] )
这就是咱们前面在浏览器中发送ws请求,可是没法创建链接的缘由!
若是scope的type属性不是http,那么弹出ValueError异常,并提示不支持该类链接!
再看看人家写的注释,明明白白的写着Serve only HTTP connections. FIXME: Allow to override this.
。翻译过来就是只支持HTTP链接,请本身重写这部份内容修复这个缺陷。FIXME!FIXME!
好吧,我认可白高兴了一场。
与Django3.0关于异步通讯的初体验很很差,有下面几点猜想:
因为相关资料太少,多方查找,听说:
好了,关于Django3.0的事就说到这里,更多Django的教程和博客,能够访问个人官网http://www.liujiangblog.com,或者收藏个人微信公众号‘Django之家
’。文中内容若是有错误,请多批评指正,谢谢!