一、开发示例:首页点赞实时更新


返回

1.1 安装

  • pip3 install channels
  • pip3 install channels-redis
  • pip3 install asgiref

1.2 后端核心代码

  • 配置settings.py

    INSTALLED_APPS = [
        ...,
        'channels',
    ]
    # channels配置
    ASGI_APPLICATION = '项目名.asgi.application'
    CHANNEL_LAYERS = {
        'default': {
            'BACKEND': 'channels_redis.core.RedisChannelLayer',
            'CONFIG': {
                "hosts": [('0.0.0.0', 6379)],
            },
        },
    }
    
    
  • asgi.py

    import os
    import django
    
    os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'helloxjn.settings')
    django.setup()  # 置顶,防止运行daphne时报错
    
    from channels.security.websocket import AllowedHostsOriginValidator
    from channels.auth import AuthMiddlewareStack
    from channels.routing import ProtocolTypeRouter, URLRouter
    from channels.routing import ProtocolTypeRouter
    from django.core.asgi import get_asgi_application
    import app_site.routing
    
    application = ProtocolTypeRouter({
        "http": get_asgi_application(),
        # channels websocket配置
        "websocket": AllowedHostsOriginValidator(
            AuthMiddlewareStack(
                URLRouter(
                    # 解耦:路由分发
                    app_site.routing.websocket_urlpatterns
                )
            ),
        ),
    })
    
    
  • 路由app_site/routing.py

    from django.urls import re_path
    from . import consumers
    
    websocket_urlpatterns = [
        # 路由分发
        re_path(r'home/(?P<room_name>\w+)/$', consumers.ChatConsumer.as_asgi()),
    ]
    
    
  • 消费者app_site/consumers.py

    import json
    from channels.generic.websocket import AsyncWebsocketConsumer
    from utils.db_redis import r
    
    
    class ChatConsumer(AsyncWebsocketConsumer):
        async def connect(self):
            """ 连接websocket """
            self.room_name = self.scope['url_route']['kwargs']['room_name']
            self.room_group_name = 'chat_%s' % self.room_name
    
            await self.channel_layer.group_add(
                self.room_group_name,
                self.channel_name
            )
    
            await self.accept()
    
        async def disconnect(self, close_code):
            """ 断开连接 """
            await self.channel_layer.group_discard(
                self.room_group_name,
                self.channel_name
            )
    
        async def receive(self, text_data):
            """ 从websocket收到消息 """
    
            # 定制自己的业务逻辑
            like_num = r.incrby('like_num', 1)
    
            # 将更新后的数据发布到websocket
            await self.channel_layer.group_send(
                self.room_group_name,
                {
                    'type': 'chat_message',
                    'message': like_num
                }
            )
    
        async def chat_message(self, event):
            """ 发布数据到websocket """
            await self.send(text_data=json.dumps({
                'message': event['message']
            }))
    
    

1.3 前端核心代码

  • javascript代码

    // 使用channels完成实时更新点赞
    let is_close = false;
    const chatSocket = new WebSocket(`ws://${window.location.host}/home/like_num/`);  // http连接
    // const chatSocket = new WebSocket(`wss://${window.location.host}/home/like_num/`);  // https连接
    // 收到websocket实时发布的数据
    chatSocket.onmessage = function (e) {
        $('.like-num').html(JSON.parse(e.data).message);
    };
    // 关闭连接
    chatSocket.onclose = function (e) {
        console.error('websocket 连接断开');
        is_close = true;
    };
    
    //  点赞
    function send_like() {
        // 发送数据到websocket
        chatSocket.send(JSON.stringify({
            'message': '点赞了'
        }));
        ...
    }
    
    
返回