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

Django Channels实时聊天项目遭遇403 CSRF验证失败问题求助

问题解决:Django实时聊天室CSRF错误与消息不显示问题

一、CSRF 403错误修复

你添加e.preventDefault()和return false后仍报错,核心原因是绑定的是按钮click事件,未彻底阻止表单的默认submit行为。按以下两种方式修复:

方案1:修改按钮类型

将按钮的默认submit类型改为button,从根源避免表单自动提交:

<button type="button" class="px-5 py-3 rounded-xl text-white bg-teal-600 hover:bg-teal-700" id="chat-message-submit">
    send
</button>

方案2:绑定表单submit事件

放弃按钮click绑定,改为监听表单的submit事件,确保默认行为被完全阻止:

document.querySelector('form').onsubmit = function(e){
    e.preventDefault();
    const messageInputDom = document.querySelector('#chat-message-input');
    const message = messageInputDom.value.trim();
    if (!message) {
        alert('Type something!');
        return;
    }
    chatSocket.send(JSON.stringify({
        'message': message,
        'username': userName,
        'room': roomName,
    }));
    messageInputDom.value = '';
    return false;
}

同时,按Django规范在表单内添加CSRF token(即使使用WebSocket,保留表单的POST方法时建议添加):

<form method='POST' action='.' class='flex'>
    {% csrf_token %}
    <input type="text" name="content" class="flex-1 mr-3" placeholder="Your message..." id="chat-message-input">
    <!-- 按钮元素 -->
</form>

二、消息无法显示到chat-messages的排查与修复

消息不显示需从WebSocket连接、后端消费逻辑、前端渲染三个环节逐一排查:

1. 验证WebSocket连接状态

打开浏览器控制台(F12),切换到Network标签的WS分类:

  • 检查是否存在ws://你的域名/ws/房间slug/的连接,状态为101 Switching Protocols则连接成功;
  • 若连接失败,确认routing.py的路径与前端拼接的路径一致,且Django Channels的ASGI配置正确。

2. 检查后端消费逻辑

在consumers.py中添加日志,确认消息是否被正确接收和广播:

async def receive(self, text_data):
    data = json.loads(text_data)
    print(f"Received message: {data}")  # 打印接收的消息
    message = data['message']
    username = data['username']
    room = data['room']
    await self.channel_layer.group_send(
        self.room_group_name,
        {
            'type': 'chat_message',
            'message': message,
            'username': username,
            'room': room,
        }
    )

async def chat_message(self, event):
    print(f"Broadcasting message: {event}")  # 打印待广播的消息
    message = event['message']
    username = event['username']
    room = event['room']

    await self.send(text_data=json.dumps({
        'message': message,
        'username': username,
        'room': room,
    }))

启动服务后查看终端日志,若没有打印内容,说明WebSocket消息未到达后端,需检查前端发送逻辑。

3. 修复前端渲染逻辑

优化HTML拼接方式(用模板字符串替代字符串拼接,减少语法错误),并添加日志确认数据接收情况:

chatSocket.onmessage = function(e) {
    console.log('Received message from server:', e.data);
    const data = JSON.parse(e.data);
    if (data.message){
        const html = `
            <div class="p-4 bg-gray-200 rounded-xl">
                <p class="font-semibold">${data.username}</p>
                <p>${data.message}</p>
            </div>
        `;
        document.querySelector('#chat-messages').innerHTML += html;
        // 自动滚动到聊天底部
        document.querySelector('#chat-messages').scrollTop = document.querySelector('#chat-messages').scrollHeight;
    }else {
        alert('Type something!')
    }
}

若控制台打印了Received message from server但页面无显示,检查#chat-messages元素是否存在,或CSS样式是否导致内容被隐藏。

4. 确认Channel Layer配置

开发环境下需在settings.py配置内存型Channel Layer:

CHANNEL_LAYERS = {
    "default": {
        "BACKEND": "channels.layers.InMemoryChannelLayer"
    }
}

生产环境需安装channels_redis并配置Redis作为后端。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.12 05:01:26