如何获取Django Websocket已登录用户的成员列表?
解决方案:获取Django Websocket群组的已登录用户列表
Django Channels 的 Channel Layer 本身没有内置方法直接获取群组成员列表,因此需要自行维护群组的成员信息。最适合实时场景的方案是用 Redis 存储成员数据(因为 Channel Layer 通常也用 Redis 做后端,兼容性好),以下是具体实现步骤:
1. 准备工作
- 确保已安装 Redis 并启动服务
- 安装 Redis Python 客户端:
pip install redis - 确保 Django Channels 已配置 Redis 作为 Channel Layer 后端(在
settings.py中):
CHANNEL_LAYERS = { "default": { "BACKEND": "channels_redis.core.RedisChannelLayer", "CONFIG": { "hosts": [("127.0.0.1", 6379)], }, }, }
2. 修改 ChatConsumer 实现成员管理
import json import redis from channels.generic.websocket import AsyncWebsocketConsumer # 初始化 Redis 客户端,根据你的 Redis 配置调整参数 redis_client = redis.Redis(host='localhost', port=6379, db=0) class ChatConsumer(AsyncWebsocketConsumer): async def connect(self): self.room_group_name = self.scope["url_route"]["kwargs"]["room_name"] self.user = self.scope['user'] # 拒绝未登录用户连接 if not self.user.is_authenticated: await self.close() return # 将当前客户端加入 Channel Layer 群组 await self.channel_layer.group_add( self.room_group_name, self.channel_name ) # 将用户信息存入 Redis 集合(用 username 作为唯一标识) redis_key = f"room_members:{self.room_group_name}" redis_client.sadd(redis_key, self.user.username) # 获取当前群组的所有成员,转换为字符串列表 member_list = [member.decode('utf-8') for member in redis_client.smembers(redis_key)] await self.accept() # 向当前客户端发送初始成员列表 await self.send(text_data=json.dumps({ 'channel_name': self.channel_name, 'room_group_name': self.room_group_name, 'member_list': member_list })) # 通知群组内其他用户更新成员列表 await self.channel_layer.group_send( self.room_group_name, { 'type': 'broadcast_member_list', 'member_list': member_list } ) async def disconnect(self, close_code): # 从 Channel Layer 群组移除当前客户端 await self.channel_layer.group_discard( self.room_group_name, self.channel_name ) # 已登录用户断开时,从 Redis 移除其信息 if self.user.is_authenticated: redis_key = f"room_members:{self.room_group_name}" redis_client.srem(redis_key, self.user.username) # 获取更新后的成员列表 updated_members = [member.decode('utf-8') for member in redis_client.smembers(redis_key)] # 通知其他用户成员列表更新 await self.channel_layer.group_send( self.room_group_name, { 'type': 'broadcast_member_list', 'member_list': updated_members } ) # 处理群组内的成员列表广播消息 async def broadcast_member_list(self, event): await self.send(text_data=json.dumps({ 'type': 'member_list_updated', 'member_list': event['member_list'] }))
3. 关键逻辑说明
- 成员存储:用 Redis 集合存储每个群组的成员,集合的键格式为
room_members:{群组名},值为用户的username(也可以用user_id更稳定)。 - 连接时处理:用户连接成功后,将其加入 Redis 集合,然后获取完整成员列表返回给当前客户端,并广播给群组内所有用户。
- 断开时处理:用户断开连接后,从 Redis 集合中移除其信息,再次广播更新后的成员列表,确保所有客户端的列表都是最新的。
- 认证校验:通过
self.scope['user']获取登录用户,拒绝未认证用户连接,避免匿名用户混入。
4. 可选优化
- 如果需要存储更多用户信息(如头像、在线状态),可以用 Redis 哈希表代替集合,键为用户 ID,值为用户信息的 JSON 字符串。
- 若需重启服务后保留成员数据,可开启 Redis 的持久化功能,或者结合数据库做持久化备份。
- 对于匿名用户,可以生成唯一的会话 ID(如
self.scope['session'].session_key)作为标识存入 Redis。
内容的提问来源于stack exchange,提问作者whitebear
相关产品推荐
相关产品推荐

