Python+Django+Channels之Consumers(用户)

个人博客,欢迎来撩 fangzengye.com

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

 

 

 

 

 

 

 

 

 

 

 

posted @ 2020-12-13 19:29  开源的Boy  阅读(448)  评论(0)    收藏  举报