Django Channels实时聊天发送消息后如何无刷新展示用户头像
解决方案
问题根源
你当前代码中使用的{{ message.author.profile.image.url }}是Django模板在页面首次加载时就渲染完成的静态固定值,不会跟随后续WebSocket接收到的不同用户消息动态更新,因此无法匹配每个发信用户的头像。
修改步骤
1. 修改Consumers.py,在消息推送时携带对应用户头像URL
你需要在异步逻辑中查询发信用户的头像地址,并随消息一起推送给前端,修改后代码如下:
import json from channels.db import sync_to_async from channels.generic.websocket import AsyncWebsocketConsumer from django.contrib.auth.models import User from .models import Message class ChatRoomConsumer(AsyncWebsocketConsumer): async def connect(self): self.room_name = self.scope['url_route']['kwargs']['room_name'] self.room_group_name = 'chat_%s' % self.room_name print(self.room_group_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 ) # 新增同步方法:根据用户名获取用户头像URL @sync_to_async def get_user_avatar(self, username): user = User.objects.get(username=username) return user.profile.image.url async def receive(self, text_data): text_data_json = json.loads(text_data) message = text_data_json['message'] username = text_data_json['username'] room = text_data_json['room'] await self.save_message(username, room, message) # 获取发信用户的头像URL avatar_url = await self.get_user_avatar(username) await self.channel_layer.group_send( self.room_group_name, { 'type': 'chatroom_message', 'message': message, 'username': username, 'avatar_url': avatar_url, # 新增头像字段 } ) async def chatroom_message(self, event): message = event['message'] username = event['username'] avatar_url = event['avatar_url'] # 取出头像字段 await self.send(text_data=json.dumps({ 'message': message, 'username': username, 'avatar_url': avatar_url, # 推送给前端 })) @sync_to_async def save_message(self, username, room, message): user = User.objects.get(username = username) Message.objects.create(author = user, room = room, content = message)
2. 修改前端JavaScript代码,动态渲染头像
将原来的静态模板变量替换为WebSocket返回的动态头像地址,同时注意不要给多个头像设置重复的id,修改onmessage逻辑即可:
chatSocket.onmessage = function (e) { const data = JSON.parse(e.data); console.log(data) if (data.message) { // 用模板字符串插入后端返回的头像地址,id改为class避免重复 document.querySelector('#chat-text').innerHTML += (`<img class="chat-avatar" src="${data.avatar_url}" alt="${data.username}"> ${data.username}<br>${data.message}<br>`); } }
修改完成后发送消息即可实时加载对应用户的头像,无需刷新页面。
内容的提问来源于stack exchange,提问作者IceSpeaker
相关产品推荐
相关产品推荐

