如何在Django中实现游戏/电影模型创建时自动通知用户
实现新游戏/电影发布时自动发送通知的方案
第一步:修正模型结构
你当前的Movies模型嵌套在Games类中,这是错误写法,先调整为独立模型:
# games model GAME_TYPE=( ("action", "action"), ("adventure", "adventure"), ("racing", "racing"), ("puzzle", "puzzle"), ) MOV_TYPE=( ("action", "action"), ("adventure", "adventure"), ("sci-fi", "sci-fi"), ("horror", "horror"), ("drama", "drama"), ) GAME_OS=( ("Windows", "Windows"), ("Android", "Android"), ) class Games(models.Model): name=models.CharField(max_length=50) type=models.CharField(max_length=40, choices=GAME_TYPE) os=models.CharField(max_length=15, choices=GAME_OS) img=models.ImageField() developer=models.CharField(max_length=50) version=models.CharField(max_length=10) ratings=models.CharField(max_length=10) description=models.TextField() def __str__(self) -> str: return self.name class Movies(models.Model): name=models.CharField(max_length=50) type=models.CharField(max_length=40, choices=MOV_TYPE) description=models.TextField() released=models.DateField() def __str__(self) -> str: return self.name
第二步:创建通知模型(存储站内通知)
如果需要实现站内通知,先创建Notification模型记录通知内容与状态:
from django.conf import settings from django.db import models class Notification(models.Model): user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True, blank=True) CONTENT_TYPE_CHOICES = ( ("game", "新游戏"), ("movie", "新电影"), ) content_type = models.CharField(max_length=10, choices=CONTENT_TYPE_CHOICES) content_id = models.IntegerField() # 关联对应的游戏/电影ID message = models.TextField() is_read = models.BooleanField(default=False) created_at = models.DateTimeField(auto_now_add=True) def __str__(self): return f"{self.user.username if self.user else '全体用户'}: {self.message[:20]}"
第三步:用Django信号触发通知逻辑
利用Django的post_save信号,在新增游戏/电影时自动执行通知生成逻辑:
1. 编写信号处理函数
在你的app目录下新建signals.py,添加以下代码:
from django.db.models.signals import post_save from django.dispatch import receiver from django.conf import settings from .models import Games, Movies, Notification @receiver(post_save, sender=Games) def send_new_game_notification(sender, instance, created, **kwargs): if created: # 仅在新增数据时触发 message = f"新游戏上线:{instance.name},类型:{instance.get_type_display()},支持平台:{instance.get_os_display()}" # 给所有用户发送站内通知 users = settings.AUTH_USER_MODEL.objects.all() for user in users: Notification.objects.create( user=user, content_type="game", content_id=instance.id, message=message ) # 可选:添加邮件通知 # from django.core.mail import send_mail # send_mail( # subject="新游戏上线通知", # message=message, # from_email=settings.DEFAULT_FROM_EMAIL, # recipient_list=[user.email for user in users], # fail_silently=False, # ) @receiver(post_save, sender=Movies) def send_new_movie_notification(sender, instance, created, **kwargs): if created: message = f"新电影发布:{instance.name},类型:{instance.get_type_display()},上映日期:{instance.released.strftime('%Y-%m-%d')}" users = settings.AUTH_USER_MODEL.objects.all() for user in users: Notification.objects.create( user=user, content_type="movie", content_id=instance.id, message=message ) # 可选:添加邮件通知 # from django.core.mail import send_mail # send_mail( # subject="新电影发布通知", # message=message, # from_email=settings.DEFAULT_FROM_EMAIL, # recipient_list=[user.email for user in users], # fail_silently=False, # )
2. 注册信号
修改app目录下的apps.py,确保Django启动时加载信号:
from django.apps import AppConfig class YourAppNameConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'your_app_name' # 替换成你的app名称 def ready(self): import your_app_name.signals # 替换成你的app名称
第四步:前端展示通知(可选)
在用户中心页面查询并展示该用户的未读通知:
# views.py from django.shortcuts import render from .models import Notification def user_notifications(request): notifications = Notification.objects.filter(user=request.user, is_read=False).order_by('-created_at') # 可选:标记所有未读通知为已读 # notifications.update(is_read=True) return render(request, 'notifications.html', {'notifications': notifications})
可选:添加用户订阅功能
如果不想给所有用户发通知,可新增订阅模型,让用户选择订阅的游戏/电影类型:
class UserSubscription(models.Model): user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE) subscribed_game_types = models.CharField(max_length=200, blank=True) # 用逗号分隔类型,如"action,adventure" subscribed_movie_types = models.CharField(max_length=200, blank=True) def __str__(self): return f"{self.user.username}的订阅"
然后修改信号处理函数,仅给订阅对应类型的用户发通知:
@receiver(post_save, sender=Games) def send_new_game_notification(sender, instance, created, **kwargs): if created: message = f"新游戏上线:{instance.name},类型:{instance.get_type_display()},支持平台:{instance.get_os_display()}" # 过滤订阅了该游戏类型的用户 subscribed_users = settings.AUTH_USER_MODEL.objects.filter( usersubscription__subscribed_game_types__contains=instance.type ) for user in subscribed_users: Notification.objects.create( user=user, content_type="game", content_id=instance.id, message=message )
内容的提问来源于stack exchange,提问作者Byansi
相关产品推荐
相关产品推荐

