https://channels.readthedocs.io/en/latest/introduction.html
(编辑器有问题。。,代码请自行格式化)

安装

pip install -U channels

或安装最新版本:

git clone git@github.com:django/channels.git
cd channels
pip install -e .  # the dot specifies the current repo

setting配置

  1. 添加 channels 到你的 INSTALLED_APPS 设置:
INSTALLED_APPS = (
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    ...
    'channels',
)
  1. 添加ASGI_APPLICATION 到 setting.py
ASGI_APPLICATION = "mysite.routing.application"
  1. 添加 CHANNEL_LAYERS相关配置 到 setting.py
CHANNEL_LAYERS = {
    'default': {
        'BACKEND': 'channels_redis.core.RedisChannelLayer',
        'CONFIG': {
            "hosts": [('127.0.0.1', 6379)],  # 需修改
        },
    },
}

编写代码

  1. 添加routing
#mysite/routing.py
from . import consumers
application = ProtocolTypeRouter({

    # WebSocket  handler
    "websocket": AuthMiddlewareStack(
        URLRouter([
                path('ws/minichat/', consumers.MiniChatConsumer),
        ])
    ),
})
  1. Consumer消费者编写
    1. 最基本的同步消费这代码,同步代码中可直接调用orm数据模型。
    class ChatConsumer(WebsocketConsumer):
                def connect(self):
                    self.username = "Anonymous"
                    self.accept()
                    self.send(text_data="[Welcome %s!]" % self.username)
    
                def receive(self, *, text_data):
                    if text_data.startswith("/name"):
                        self.username = text_data[5:].strip()
                        self.send(text_data="[set your username to %s]" % self.username)
                    else:
                        self.send(text_data=self.username + ": " + text_data)
    
                def disconnect(self, message):
                    pass
    
    1. 基础的异步代码,所有操作异步,不能直接调用orm
    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
    
    1. 常用示例 同步channel,中调用异步方法
    class MiniChatConsumer(WebsocketConsumer):
    def connect(self):
        self.room_group_name='jcfcchat'
        async_to_sync(self.channel_layer.group_add)(
            self.room_group_name,
            self.channel_name
        )
        self.accept()
    
    def disconnect(self, close_code):
        async_to_sync(self.channel_layer.group_discard)(
            self.room_group_name,
            self.channel_name
        )
    
    def receive(self, text_data=None, bytes_data=None):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        user=text_data_json['user']
        async_to_sync(self.channel_layer.group_send)(
            self.room_group_name,
            {
                'type': 'chat_message',
                'message': message,
                "user":user
            }
        )
    # Receive message from room group
    def chat_message(self, event):
        message = event['message']
        user = event['user']
        # Send message to WebSocket
        self.send(text_data=json.dumps({
            'user':user,
            'time':time.strftime('%H:%M:%S',time.localtime(time.time())),
            'message': message
        }))
    
    
    1. 异步 数据库连接:database_sync_to_async

    要使用它,请在单独的函数或方法中编写ORM查询,然后database_sync_to_async像这样调用它:

    from channels.db import database_sync_to_async
    
    async def connect(self):
        self.username = await database_sync_to_async(self.get_name)()
    def get_name(self):
        return User.objects.all()[0].name
    

    也可以将它用作装饰者:

    from channels.db import database_sync_to_async
    
    async def connect(self):
        self.username = await self.get_name()
    @database_sync_to_async
    def get_name(self):
        return User.objects.all()[0].name
    

发表评论

邮箱地址不会被公开。