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

如何在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  # 可选:把书籍对象关联到通知,方便后续跳转
                )

关键细节说明

  1. change参数的作用:当你在Admin里创建新对象时,change是False;更新已有对象时是True,用if not change确保只在创建新书时发通知,避免重复触发。
  2. 查询关注者的方式:因为我们给favorites_authors设置了related_name='followers',所以可以直接用writer.followers.all()拿到所有收藏该作者的Profile,比直接查中间表更优雅。如果你的模型没有设置related_name,可以用Profile.objects.filter(favorites_authors=writer)来查询。
  3. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.27 07:34:37