Django Channels配置

2021-12-07 16:58:55 浏览数 (1)

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文档

0 人点赞