Django使用signals搭建通知系统时如何从接收列表移除发件人
问题根源
- 类型匹配错误:
notifications列表存储的是Notifications模型实例,而你用User类型的sender判断是否在列表中,二者类型完全不同,判断条件永远为False,移除逻辑根本不会执行。 - 实例匹配错误:即便调整了判断逻辑,调用
remove()时新创建的Notifications实例和列表中已有的实例是两个完全独立的对象,哪怕字段值完全一致,remove()方法也无法匹配到列表中已有的实例,不会执行删除。 - 变量取值错误:循环遍历完所有
receivers后,receiver变量存储的是最后一个被遍历的用户,不是发件人本人,你构造要删除的Notifications实例时receiver参数本身就传错了,更不可能匹配到正确的对象。 - 额外隐患:你自定义的
sender变量和Django信号函数默认的第一个位置参数sender重名,容易引发不必要的逻辑冲突。
修复方案
推荐最优的处理方式:直接在生成通知列表的阶段就过滤掉发件人,不需要先生成全量列表再做删除,性能更高逻辑也更清晰,两种实现方式可选:
方案1:数据库层面直接过滤收件人(最高效)
直接在查询用户列表时就排除发件人,从根源上不会生成发件人的通知实例:
def global_noti(sender, instance, *args, **kwargs): global_notify = instance # 重命名避免和信号默认参数冲突 notify_sender = global_notify.user # 查询时直接排除发件人,不需要后续过滤 receivers = User.objects.exclude(id=notify_sender.id) text = global_notify.text if global_notify.is_published == 'global_notification': notifications = [] for receiver in receivers: notifications.append(Notifications( sender=notify_sender, receiver=receiver, text_preview=text, notification_type="global_noti" )) Notifications.objects.bulk_create(notifications)
方案2:循环生成通知时跳过发件人
如果需要保留全量用户查询的逻辑,也可以在循环生成通知实例时加判断跳过发件人:
def global_noti(sender, instance, *args, **kwargs): global_notify = instance notify_sender = global_notify.user receivers = User.objects.all() text = global_notify.text if global_notify.is_published == 'global_notification': notifications = [] for receiver in receivers: # 接收人和发件人一致时直接跳过,不加入列表 if receiver == notify_sender: continue notifications.append(Notifications( sender=notify_sender, receiver=receiver, text_preview=text, notification_type="global_noti" )) Notifications.objects.bulk_create(notifications)
内容的提问来源于stack exchange,提问作者boyenec
相关产品推荐
相关产品推荐

