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

Django中如何向多个选定用户发送相同通知且保留各用户is_seen状态

实现方案

核心思路

将公共通知内容和用户侧的独立状态拆分,通过Django带中间表的多对多关联实现,既避免同一条通知内容重复存储,也能满足每个用户拥有独立的已读状态需求。

具体模型定义

from django.db import models
from django.contrib.auth import get_user_model

User = get_user_model()

class Notification(models.Model):
    """公共通知主表,同一条通知内容仅存储一次"""
    content = models.TextField(verbose_name="通知内容")
    create_time = models.DateTimeField(auto_now_add=True, verbose_name="发布时间")
    # 可按需扩展其他公共字段,比如通知类型、跳转链接、发布人等
class UserNotification(models.Model):
    """用户与通知的关联中间表,存储每个用户的独立状态"""
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="user_notifications", verbose_name="所属用户")
    notification = models.ForeignKey(Notification, on_delete=models.CASCADE, related_name="user_records", verbose_name="关联通知")
    is_seen = models.BooleanField(default=False, verbose_name="是否已读")
    receive_time = models.DateTimeField(auto_now_add=True, verbose_name="接收时间")

    class Meta:
        # 约束同一个用户和同一条通知仅存在一条关联记录
        unique_together = ('user', 'notification')

常用操作示例

  • 给多个选定用户批量发送同一条通知
# 第一步创建公共通知内容
new_noti = Notification.objects.create(content="系统将于今日22:00进行维护升级")
# 假设selected_users为你筛选出的目标用户查询集
bulk_records = [UserNotification(user=user, notification=new_noti) for user in selected_users]
# 批量插入提升性能
UserNotification.objects.bulk_create(bulk_records)
  • 查询指定用户的所有未读通知
unread_list = UserNotification.objects.filter(
    user=request.user, 
    is_seen=False
).select_related('notification').order_by('-receive_time')
# 遍历unread_list时取notification.content即可获取通知内容
  • 标记某条通知为已读
# user_noti_id为用户侧通知关联记录的id
UserNotification.objects.filter(id=user_noti_id, user=request.user).update(is_seen=True)

方案优势

  • 同一条通知内容仅存储一次,节省存储空间
  • 所有用户的已读状态完全独立,互不干扰
  • 扩展性强,后续需要新增用户侧通知属性(比如是否置顶、是否删除)时,直接在UserNotification表添加字段即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 07:57:03