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

使用Django Channels开发通知应用时,await database_sync_to_async报错求助

问题解决:Django Channels异步上下文同步操作错误

核心问题分析

你遇到的SynchronousOnlyOperation错误,根源在于get_notifications方法中直接返回了NotificationSerializer实例,而非序列化后的data属性。虽然用了@database_sync_to_async装饰器,但Serializer实例内部仍可能包含未完成的同步操作,在异步上下文访问时触发错误。另外代码里还有两处逻辑错误需要修正:

具体修复步骤

1. 修正Serializer调用,返回序列化后的数据

修改get_notifications方法,将new_messages替换为new_messages.data:

@database_sync_to_async
def get_notifications(self, user):
    new_messages = NotificationSerializer(
        Notification.objects.filter(content=1, users_notified__in=[user]), 
        many=True
    ).data  # 新增.data获取序列化结果

    notifs = {
        "new_messages": new_messages
    }

    return notifs

2. 修正connect方法的断开逻辑

当前代码中,无论用户是否合法,执行完if user块后都会调用disconnect(401),导致刚建立的连接被立刻断开。调整为仅当用户未认证时才断开:

async def connect(self):
    user = self.scope["user"]

    if user.is_authenticated:  # 用is_authenticated准确判断用户有效性
        self.channel_name = user.username
        self.room_group_name = 'notification_%s' % self.channel_name
        
        notification = await self.get_notifications(user)
        print("Notification", notification)

        await self.channel_layer.group_add(
            self.room_group_name,
            self.channel_name
        )

        await self.accept()
    else:
        await self.disconnect(401)  # 仅未认证用户执行断开操作

3. 修正disconnect方法的分组操作

Django Channels中没有group_discard方法,正确的移除分组方法是group_remove:

async def disconnect(self, close_code):
    # 增加属性存在判断,避免未初始化时报错
    if hasattr(self, 'room_group_name') and hasattr(self, 'channel_name'):
        await self.channel_layer.group_remove(
            self.room_group_name,
            self.channel_name
        )

为什么之前聊天应用能正常运行?

大概率是聊天应用中你直接操作了数据库模型的保存(如message.save()),这类操作被database_sync_to_async正确包裹;而本次通知系统中使用Serializer时遗漏了取.data的步骤,导致Serializer的同步逻辑暴露在异步上下文里。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 14:30:16