Django Channels
Channels包装了Django的原生异步视图支持(Django3之后支持异步视图),允许Django项目不仅可以处理HTTP,还可以处理WebSockets,MQTT等。Channels提供了与Django的身份验证系统,会话系统等的集成,使得将纯HTTP项目扩展到其他协议比以往任何时候都更容易。因此,通常我们在Django3上实现websocket还是会使用channels
安装channels
这个非常简单,执行pip安装即可。
pip3 install channels
注意,在安装channels时候,会附带安装一系列东西,其中最重要的是Daphne服务器,asgiref模块。因为我们会在程序中使用asgiref模块,在运行项目的时候,会使用Daphne.
配置channels
下面以一个真实的例子chatroom,作为演示在Django中配置channels。
首先在settings.py中进行注册和asgi网关配置。
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'channels',
'chat',
]
WSGI_APPLICATION = 'chatroom.wsgi.application'
ASGI_APPLICATION = "chatroom.asgi.application"
然后,在项目的settings.py同级目录下的asgi.py文件中加入下面的内容:Django2.2是默认没有asgi.py文件,手动创建一个即可。Django3之后,项目默认会生成一个asgi.py文件。 默认内容如下:
import os
from django.core.asgi import get_asgi_application
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'chatroom.settings')
application = get_asgi_application()
默认的asgi虽然支持了异步服务,但是仍然不支持websocket。因此我们要修改asgi.py的内容如下所示:
import os
from django.core.asgi import get_asgi_application
from channels.routing import ProtocolTypeRouter, URLRouter
from . import routings
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'chatroom.settings')
application = ProtocolTypeRouter(
{
"http": get_asgi_application(),
"websocket": URLRouter(routings.websocket_urlpatterns),
}
)
Django2.2不支持asgi,因此无法从django.core.asgi导入get_asgi_application,需要使用如下配置。
import os
import django
from channels.http import AsgiHandler
from channels.routing import ProtocolTypeRouter
from . import routings
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'chatroom.settings')
django.setup()
application = ProtocolTypeRouter({
"http": AsgiHandler(),
"websocket": URLRouter(routings.websocket_urlpatterns),
})
经过这样的配置之后,我们之后运行项目的时候不在使用WSGI启动,而是使用ASGI启动项目。
接下来,在settings.py同级目录创建一个名为routings.py的文件,就是我们刚才在asgi.py中导入的那个文件。然后在routings.py文件中写上如下的内容:
from django.urls import re_path
from chat import consumers
websocket_urlpatterns = [
re_path("^room/(?P<group>\w+)", consumers.ChatConsumer.as_asgi()),
]
最后,在chat这个app的目录下创建consumers.py文件(如果你没有该app,那就需要创建一个,前面我们已经注册过这个app了)。在consumers.py中写入如下内容:
from channels.generic.websocket import WebsocketConsumer
from channels.exceptions import StopConsumer
class ChatConsumer(WebsocketConsumer):
def websocket_connect(self, message):
self.accept()
def websocket_receive(self, message):
self.send(text_data='OK')
def websocket_disconnect(self, message):
raise StopConsumer()
运行项目
python3 manage.py migrate # 执行迁移
python3 manage.py runserver 8080 # 运行项目
项目执行以后,可以观察到使用的是ASGI,而非WSGI. 现在,打开浏览器或者Postman等工具进行测试即可,这里使用浏览器的控制台发生websocket请求进行测试。如下图所示 现在,我们看一下服务器上的请求记录。 首先是“握手(HANDSHAKING)”,握手成功就连接上了(CONNECT)。当前端发送关闭之后,服务器收到以后,执行断开连接(DISCONNECT)操作。
到此为止,我们就完成了Django Channels的配置。下一篇讲述如何使用channels。
参考资料
channels文档
|