如何在Django中扩展管理员视图以实现新增书籍时发送通知?
没问题,这就给你一步步实现这个需求,核心是重写Django Admin里的save_model方法,在书籍保存后触发通知逻辑:
第一步:确认你的模型结构(参考示例)
假设你的模型大概是这样的(如果和你的实际模型有出入,调整字段名即可):
# models.py from django.db import models from django.contrib.auth.models import User class Author(models.Model): name = models.CharField(max_length=100) # 其他字段比如简介、头像等... class Profile(models.Model): user = models.OneToOneField(User, on_delete=models.CASCADE) favorites_authors = models.ManyToManyField(Author, related_name='followers') # 其他用户相关字段... class Book(models.Model): title = models.CharField(max_length=200) author = models.ForeignKey(Author, on_delete=models.CASCADE) category = models.CharField(max_length=50) publication_date = models.DateField() # 其他书籍字段...
第二步:自定义Book的Admin类,添加通知逻辑
在你的admin.py里,创建自定义的BookAdmin类,重写save_model方法——这是Django Admin提供的钩子,专门用来处理保存前后的自定义操作:
# admin.py from django.contrib import admin from .models import Book from notifications.signals import notify @admin.register(Book) class BookAdmin(admin.ModelAdmin): # 配置Admin页面显示的字段和表单,根据你的需求调整 list_display = ('title', 'author', 'category', 'publication_date') fields = ('title', 'author', 'category', 'publication_date') def save_model(self, request, obj, form, change): # 先调用父类的save方法,把书籍保存到数据库 super().save_model(request, obj, form, change) # 只有创建新书籍时才发通知(更新书籍时不触发) if not change: # 获取当前书籍的作者对象 writer = obj.author # 找到所有把该作者设为喜爱的用户Profile # 这里用Django ORM的关联查询,比直接查中间表更简洁 follower_profiles = writer.followers.all() # 循环给每个关注者发通知 for profile in follower_profiles: # 从Profile拿到对应的User对象(django-notifications要求recipient是User实例) recipient = profile.user # 发送通知,这里可以自定义verb的内容 notify.send( sender=writer, # 通知的发送者,这里用作者对象,也可以用request.user(当前操作的管理员) recipient=recipient, verb=f"新书上架啦:《{obj.title}》,作者是你喜爱的{writer.name}!", action_object=obj # 可选:把书籍对象关联到通知,方便后续跳转 )
关键细节说明
change参数的作用:当你在Admin里创建新对象时,change是False;更新已有对象时是True,用if not change确保只在创建新书时发通知,避免重复触发。- 查询关注者的方式:因为我们给
favorites_authors设置了related_name='followers',所以可以直接用writer.followers.all()拿到所有收藏该作者的Profile,比直接查中间表更优雅。如果你的模型没有设置related_name,可以用Profile.objects.filter(favorites_authors=writer)来查询。 - django-notifications的参数:
sender可以是任何模型实例(作者、管理员用户都可以),recipient必须是User类型,所以要从Profile里取出关联的User对象。action_object是可选的,关联书籍对象后,你可以在通知模板里用它跳转到书籍详情页。
可选优化:异步处理通知
如果你的平台用户量较大,一次性给很多用户发通知会导致Admin页面卡顿,建议用Celery把通知逻辑改成异步任务:
# 示例:把通知逻辑放到Celery任务里 from celery import shared_task @shared_task def send_new_book_notifications(writer_id, book_title, book_id): writer = Author.objects.get(id=writer_id) book = Book.objects.get(id=book_id) follower_profiles = writer.followers.all() for profile in follower_profiles: notify.send( sender=writer, recipient=profile.user, verb=f"新书上架啦:《{book_title}》,作者是你喜爱的{writer.name}!", action_object=book ) # 然后在save_model里调用异步任务 def save_model(self, request, obj, form, change): super().save_model(request, obj, form, change) if not change: send_new_book_notifications.delay(obj.author.id, obj.title, obj.id)
这样Admin页面就能快速响应,通知任务在后台异步执行。
内容的提问来源于stack exchange,提问作者micleb
相关产品推荐
相关产品推荐

