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