Python+Django+Channels之Consumers(用户)
Consumers
因为建立Channels最底层的解释接口是ASGI,被用来连接复杂应用的操作接口
当然你也可以忽略consumers而使用其他Channels部分,像routing,session等等
基础布局
consumers 的子类有
channels.consumer.AsyncConsumer
channels.consumer.SyncConsumer
SyncConsumer的一个基础例子
from channels.consumer import SyncConsumer
class EchoConsumer(SyncConsumer):
def websocket_connect(self, event):
self.send({
"type": "websocket.accept",
})
def websocket_receive(self, event):
self.send({
"type": "websocket.send",
"text": event["text"],
})</code></pre>
通过在ASGI设置,我们可以获取到信息。
self.send(event)可以将事件发送到客户端或是服务器
与AsyncConsumer相似,其他的处理方法也要有self.send
from channels.consumer import AsyncConsumer
class EchoConsumer(AsyncConsumer):
async def websocket_connect(self, event):
await self.send({
"type": "websocket.accept",
})
async def websocket_receive(self, event):
await self.send({
"type": "websocket.send",
"text": event["text"],
})</code></pre>
什么时候使用AsyncConsumer或SyncConsumer?
当你使用慢同步函数循环整个事件时使用AsymcConsumer,如果你到用Django的ORM模型就应该使用SyncConsumer。一般使用SyncConsumer为默认值。
Closing Consumers关闭用户
当已连接的consumer要关闭时,需要使用http.disconnect或websocket.disconnect
当结束时会触发channels.exceptions.StopConsumer
Channel Layers
Consumer通过使用Channel Layers来相互发送消息或广播消息
Scope领域、范围
Consumuer能够接收连接所在的范围的消息
scope["path"], the path on the request. (HTTP and WebSocket)scope["headers"], raw name/value header pairs from the request (HTTP and WebSocket)scope["method"], the method name used for the request. (HTTP)
WebSocketConsumer
这个包channels.generic.websocket.WebsocketConsumer是处理发送和接收消息。
from channels.generic.websocket import WebsocketConsumer
class MyConsumer(WebsocketConsumer):
groups = ["broadcast"]
def connect(self):
# Called on connection.
# To accept the connection call:
self.accept()
# Or accept the connection and specify a chosen subprotocol.
# A list of subprotocols specified by the connecting client
# will be available in self.scope['subprotocols']
self.accept("subprotocol")
# To reject the connection, call:
self.close()
def receive(self, text_data=None, bytes_data=None):
# Called with either text_data or bytes_data for each frame
# You can call:
self.send(text_data="Hello world!")
# Or, to send a binary frame:
self.send(bytes_data="Hello world!")
# Want to force-close the connection? Call:
self.close()
# Or add a custom WebSocket error code!
self.close(code=4123)
def disconnect(self, close_code):
# Called when the socket closes</code></pre>
AsyncWebsocketConsumer
from channels.generic.websocket import AsyncWebsocketConsumer
class MyConsumer(AsyncWebsocketConsumer):
groups = ["broadcast"]
async def connect(self):
# Called on connection.
# To accept the connection call:
await self.accept()
# Or accept the connection and specify a chosen subprotocol.
# A list of subprotocols specified by the connecting client
# will be available in self.scope['subprotocols']
await self.accept("subprotocol")
# To reject the connection, call:
await self.close()
async def receive(self, text_data=None, bytes_data=None):
# Called with either text_data or bytes_data for each frame
# You can call:
await self.send(text_data="Hello world!")
# Or, to send a binary frame:
await self.send(bytes_data="Hello world!")
# Want to force-close the connection? Call:
await self.close()
# Or add a custom WebSocket error code!
await self.close(code=4123)
async def disconnect(self, close_code):
# Called when the socket closes</code></pre>
AsyncHttpConsumer
from channels.generic.http import AsyncHttpConsumer
class BasicHttpConsumer(AsyncHttpConsumer):
async def handle(self, body):
await asyncio.sleep(10)
await self.send_response(200, b"Your response bytes", headers=[
(b"Content-Type", b"text/plain"),
])
import json
from channels.generic.http import AsyncHttpConsumer
class LongPollConsumer(AsyncHttpConsumer):
async def handle(self, body):
await self.send_headers(headers=[
(b"Content-Type", b"application/json"),
])
# Headers are only sent after the first body event.
# Set "more_body" to tell the interface server to not
# finish the response yet:
await self.send_body(b"", more_body=True)
async def chat_message(self, event):
# Send JSON and finish the response:
await self.send_body(json.dumps(event).encode("utf-8"))</code></pre>
from datetime import datetime
from channels.generic.http import AsyncHttpConsumer
class ServerSentEventsConsumer(AsyncHttpConsumer):
async def handle(self, body):
await self.send_headers(headers=[
(b"Cache-Control", b"no-cache"),
(b"Content-Type", b"text/event-stream"),
(b"Transfer-Encoding", b"chunked"),
])
while True:
payload = "data: %s\n\n" % datetime.now().isoformat()
await self.send_body(payload.encode("utf-8"), more_body=True)
await asyncio.sleep(1)
参考资料https://channels.readthedocs.io/en/stable/topics/consumers.html
浙公网安备 33010602011771号