1、配置asgi.py文件
- 如果直接在项目目录下创建app,那直接拷贝官网案例,改改就行了,如下:
import os
import django
from channels.routing import get_default_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "settings")
django.setup()
application = get_default_application()
- 如果app没有直接放在项目目录下
- 要想让asgi查找到我们写的应用所在的路径,就必须把应用加到django项目的查找路径当中。见下图:
2、安装channels需要的包
- Channels;Daphne(ASGI服务器);asgiref(提供ASGI相关工具的库);channels_redis(channels对应的redis驱动)
- 可以通过pip graph查看依赖关系树
3、配置中注册channels应用
INSTALLED_APPS = [
....
'channels',
....
]
4、配置Channel Layers
CHANNEL_LAYERS = {
'default': {
'BACKEND': 'channels_redis.core.RedisChannelLayer',
'CONFIG': {
'hosts': [('localhost', 6379)],
},
},
}
5、编写consumer,调用channels提供的api
- 编写consumer
- 1.继承自Consumer类(具体的继承关系见【Django Channels】附录篇)
- 2.重写方法【以继承自WebsocketConsumer为例】
- connect
- receive
- dis_connect
- …
- 说明:【以继承自基父类AsyncConsumer为例】
- 重写的方法中,self参数会有一个scope对象,该对象相当于是django-views里的request对象
- 【注意,非基父类已对这些原生操作做了封装】self有一个send方法,send()的参数是一个字典,字典里的key是固定的【依照asgi的接口规范】,如:给字典中的”type“,通过传递不同的键值对可以实现不同的 websocket操作。如:
- ”type“的值为“websocket.accept”,表示接受websocket连接请求(websocket.accept代表的其实是accept方法)
- ”type“的值为“websocket.send”,表示主动向前端推送消息;”text“指定消息的内容
def websocket_connect(self, event) :
self.send({
"type": "websocket.accept"
})
def websocket_receive(self, event) :
self.send(
"type": "websocket.send",
"text": event["text"]
})
- 关于channels提供的api
- 注意:channels提供了两个概念:【下面为了方便读者理解,以早年使用外放收音机形式的六级听力考试做类比】
- 频道名:类似于所有人共同监听的广播音频
- 组名:类似于将考生分开的教室
- channels.layers.get_channel_layer(【频道名】)
- 可以返回一个指定名称的频道层管理器实例(下面直接使用
channel_layer
变量指代)。作用类似于django-orm里的查询集管理器(objects),它提供了众多好用的api - 若不指定名称,则使用默认名称:default
- 可以返回一个指定名称的频道层管理器实例(下面直接使用
channel_layer
.group_add ( 【组名】,【频道名】)- 加入某一个组
- 通过组名的不同可以实现消息隔离的效果
- 如:实现私聊功能和实现广播功能
- {{{width=“auto” height=“auto”}}}
channel_layer
.group_discard ( 【组名】,【频道名】)- 离开某一个组
- 注意:channels提供了两个概念:【下面为了方便读者理解,以早年使用外放收音机形式的六级听力考试做类比】
6、编写routing.py
::: tip
routing.py作用类似于django的urls.py,只是在urls基础上又增加了协议这一维度。
:::
- 1.导入协议类型解析
{{{width=“auto” height=“auto”}}}- - 2.配置协议类型解析
- {{{width=“auto” height=“auto”}}}
- 说明:
- 上面的views和consumer是伪代码,只是为了示意
- ASGI服务器会调用self.scope[“protocol”]获取协议类型,用该类型在我们配置的列表中进行匹配
- 一个连接只能由一个consumer(此处指的是广义级别的consumer)接收和处理
- 普通的HTTP请求其实无需我们手动在这里添加,框架会自动加载
- 在路由如果WebsocketConsumer的时候,如果也想像django中的url、path或re_path来路由的话,就需要使用channels.routing里提供的URLRouter来实现。如下:
- {{{width=“auto” height=“auto”}}}
- 说明:写websocket协议的路由时,通常为了和http协议的路由区分开,会在路由前加上ws前缀路径
- {{{width=“auto” height=“auto”}}}
7、编写业务逻辑
- 一般是:在视图里调用Consumer中写好的逻辑,如:推送数据到前端
- 如果只是想使用websocket协议实现在线聊天功能的话,一般并不会出现前端不停向后端推送数据的业务需求,更多的是后端不断推送,前端接收
8、指定ASGI的路由地址
- 在配置文件中加上配置:ASGI_APPLICATION,值为routings.py中定义的协议类型路由器,即:ProtocolTypeRouter实例。如下: