使用Django Channels向多管理员发送通知并批量入库的实现问题
方案1:基于现有模型优化批量插入(无需修改表结构)
你原来遍历逐条插入效率低的核心原因是每次save都会发起一次数据库请求,直接用Django ORM的bulk_create方法就能解决,不需要调整现有表结构:
- 先筛选出所有管理员用户:
admin_users = User.objects.filter(groups__name='Admin') - 批量生成Notification实例列表,不需要逐个调用
save:
notifications = [ Notification( view_name="user_approval_pending", notification_type="system_alert", sender=registered_user, # 可替换为系统内置用户 recipient=admin, title="新用户待审批", redirect_url=f"/admin/users/approve/{registered_user.id}/" ) for admin in admin_users ] # 批量插入,仅执行1次数据库请求 Notification.objects.bulk_create(notifications)
- 之后再调用Channels的
group_send给Admin组推送实时通知即可,批量插入的耗时和管理员数量几乎无关,哪怕上百个管理员也只需要一次数据库交互。
方案2:改造模型支持组通知(适合高频给用户组发通知的场景)
如果你的业务经常需要给全组发通知,可以修改Notification模型,支持单通知对应多接收人/组,减少冗余数据存储:
改造后的模型参考:
class Notification(models.Model): view_name = models.CharField(max_length=255) notification_type = models.CharField(max_length=255) sender = models.ForeignKey(User, on_delete=models.DO_NOTHING, related_name='notification_sender') # 新增:允许通知发给用户组,和recipient二选一即可 recipient_group = models.ForeignKey(Group, on_delete=models.DO_NOTHING, null=True, blank=True, related_name='group_notifications') recipient = models.ForeignKey(User, on_delete=models.DO_NOTHING, null=True, blank=True, related_name='notification_receiver') title = models.CharField(max_length=255) redirect_url = models.CharField(max_length=255) created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) # 新增:用户已读状态中间表,避免同一条组通知存多份 class NotificationReadStatus(models.Model): notification = models.ForeignKey(Notification, on_delete=models.CASCADE, related_name='read_statuses') user = models.ForeignKey(User, on_delete=models.DO_NOTHING) is_read = models.BooleanField(default=False) read_at = models.DateTimeField(null=True, blank=True) class Meta: unique_together = ('notification', 'user')
改造后的使用逻辑:
- 给Admin组发通知时,只需要创建1条Notification记录,关联到Admin组即可,不需要批量插入
- 查询用户未读通知时,关联查询用户所在组的通知+单独发给用户的通知,再过滤掉已读的即可
- 存储成本更低,尤其适合大用户组的通知场景,缺点是查询逻辑会比原来的单收件人模型稍复杂。
配套Channels推送逻辑
不管用哪种存储方案,推送逻辑都是一致的:
- 提前把所有管理员加入
admin_notification的Channels分组 - 通知入库完成后,直接调用
group_send往该分组发消息即可,所有在线管理员都能实时收到通知 - 离线管理员登录时,从数据库拉取未读通知渲染即可。
内容的提问来源于stack exchange,提问作者Pranta chakraborty
相关产品推荐
相关产品推荐

