Django付费服务快到期发送通知给用户(复盘)

需求:用户购买了该产品的付费服务,当该服务即将到期时,发送通知给用户。

实现方案:

  • 在付费服务系统中设计一个命令脚本,每天扫描所有用户,在服务到期前7天进行发送通知给用户
  • 在社区服务系统中设计API,包含创建通知、获取通知、删除通知、更改通知

1. 数据库设计

CREATE TABLE `notifications` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `message` longtext NOT NULL,
  `to_user` varchar(255) NOT NULL,
  `seen` tinyint(1) NOT NULL,
  `created_at` datetime(6) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `notifications_sysusernotification_to_user_e0c9101e` (`to_user`),
  KEY `notifications_sysusernotification_seen_9d851bf7` (`seen`),
  KEY `notifications_sysusernotification_created_at_56ffd2a0` (`created_at`)
) ENGINE=InnoDB AUTO_INCREMENT=17 DEFAULT CHARSET=utf8mb3 COLLATE=utf8mb3_general_ci;
  • message:存储通知信息
  • to_user:接收用户
  • seen:是否已读
  • created:创建时间

2. API设计

api/v2/user-notifications/:nid/seen/    #将当前用户的指定通知设为已读

api/v2/user-notifications/unseen/  #获取当前用户未读的通知

api/v2/admin/user-notifications/  #管理员给指定用户创建通知、获取所有全局通知

api/v2/admin/user-notifications/:nid/   #管理员删除指定通知

3. Model定义

class NotificationManager(models.Manager):
    def create_sys_user_notificatioin(self, msg, user):
        notification = self.create(
            message = msg,
            to_user = user,
        )
        return notification

    def unseen_notes(self, user):
        notes = self.filter(to_user=user, seen=0)
        return notes

class Notification(models.Model):
    message = models.TextField(null=False, blank=False)
    to_user = models.CharField(max_length=255, db_index=True)
    seen = models.BooleanField(default=False, db_index=True)
    created_at = models.DateTimeField(auto_now_add=True, db_index=True)
    objects = NotificationManager()

    class Meta:
        ordering = ["-created_at"]

    def update_notification_to_seen(self):
        self.seen = True
        self.save()

    def to_dict(self):
        email = self.to_user
		...

        return { 
		'email': email,
			.... 
		}

4. 方法实现

  • 管理员API
class AdminUserNotificationsView(APIView):
    authentication_classes = (TokenAuthentication, SessionAuthentication)
    permission_classes = (IsAdminUser,)

    def get(self, request):
    '''获取用户通知''''
        try:
            page = int(request.GET.get('page', 1))
            per_page = int(request.GET.get('per_page', 25))
        except Exception as e:
            ...

        start, end = (page - 1) * per_page, page * per_page
        try:
            notifications = Notification.objects.all().order_by('-id')
        except Exception as e:
            ...

        return Response({
            'notifications': [n.to_dict() for n in notifications[start: end]]
        })

    def post(self,request):
    	'''创建用户通知'''
        msg = request.data.get('msg', '')
        user = request.data.get('user', '')
        
		# arguments check
        ....
        # resource check
        try:
            User.objects.get(email=user)
        except User.DoesNotExist:
           ...

        try:
            notification = Notification.objects.create(msg, user)
        except Exception as e:
            ...

        return Response({'notification': notification.to_dict()})

class NotificationView(APIView):
    # power check
    ...

    def delete(self, request, nid):
        """
        删除指定用户通知
        """
		# arguments check
        ...
		# resource check
        notification = Notification.objects.filter(id=nid).first()
        if not notification:
            ...

        try:
            notification.delete()
        except Exception as e:
            ...

        return Response({'success': True})
  • 用户API
class UserNotificationUnseenView(APIView):
    # power check
		.....
		
    def get(self, request):
        """
        获取当前用户未读通知
        """
        user = request.user
        notifications = Notification.objects.unseen_notes(user)
        return Response({
            'notifications': [n.to_dict() for n in notifications],
        })

class UserNotificationSeenView(APIView):
    # power check
	...
    def put(self, request, nid):
        """
        将通知设为已读
        """
        user = request.user.user
        # arguments check
        ....

        # resouce check
        notification = Notification.objects.filter(id=nid).first()
        if not notification:
            ...

        if notification.to_user != user:
            ...

        # set notification to seen
        try:
            notification.update_notification_to_seen()
        except Exception as e:
            ...

        return Response({'notification': notification.to_dict()})

5. 前端请求方案

当前端用户登录时,直接请求该接口获取是否有对应通知,即componentDidMount挂载

结语

*乾坤未定,你我皆是牛马!!! *

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值