使用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
相关产品推荐
相关产品推荐

