You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Channels多标签页下消息重复存入数据库问题求助

Django Channels 多标签页重复存储消息问题排查与解决

问题原因

  • 你的代码中,receive方法通过channel_layer.group_send将消息事件广播给聊天室组内的所有消费者实例,包括消息发送者打开的多个同聊天室标签页对应的消费者
  • 每个消费者实例在处理chat_message事件时,都会调用create_chat执行数据库插入操作,标签页数量等于重复存储的消息条数

解决方案

将消息入库逻辑从chat_message方法移至receive方法中,仅在接收原始消息的环节执行一次数据库存储,再将已入库的消息数据广播给组内所有消费者,避免重复入库。

修改后的完整代码

import json

from channels.db import database_sync_to_async
from channels.generic.websocket import AsyncWebsocketConsumer

from .models import Message


class ChatConsumer(AsyncWebsocketConsumer):
    @database_sync_to_async
    def create_chat(self, sender, msg):
        return Message.objects.create(sender=sender, msg=msg)

    async def connect(self):
        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):
        text_data_json = json.loads(text_data)
        message = text_data_json['message']
        sender = text_data_json['sender']
        # 仅在接收原始消息时执行一次数据库存储
        new_msg = await self.create_chat(sender, message)
        # 广播已入库的消息数据给组内所有消费者
        await self.channel_layer.group_send(self.room_group_name, {
            'type': 'chat_message',
            'message': new_msg.msg,
            'sender': new_msg.sender,
            'id': new_msg.id  # 可选:携带消息ID,方便前端做去重或状态标记
        })

    async def chat_message(self, event):
        message = event['message']
        sender = event['sender']
        # 仅负责将消息推送给前端,不再执行数据库操作
        await self.send(text_data=json.dumps({
            'message': message,
            'sender': sender,
            'id': event.get('id')
        }))

关键说明

  • receive方法仅在用户发送消息时触发一次,在此处执行入库逻辑能确保每条消息只被存储一次
  • 广播的是已完成入库的消息数据,组内所有消费者(包括发送者的其他标签页)只需将消息转发给前端即可,无需再操作数据库

内容的提问来源于stack exchange,提问作者Mader Bobunis

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 03:44:52