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

Django admin创建BlogPost对象时post_save信号未触发问题咨询

问题根因

信号未触发的核心原因是你定义的信号接收器没有被Django加载识别,另外配套的Celery任务代码也存在语法错误会导致后续调用失败,具体问题如下:

  • 你只创建了signals.py文件,但没有通过任意一种注册方式告诉Django加载该文件,服务启动时不会读取你的信号接收器逻辑,自然触发时没有反应
  • Celery任务定义错误使用了self参数,同时直接传递模型对象给Celery任务会触发序列化异常,即使信号触发也会报错
解决步骤

1. 注册信号让Django加载

两种方案二选一即可:

方案A:通过应用配置的ready方法加载

找到apps/blogs/apps.py文件,修改配置类如下:

from django.apps import AppConfig

class BlogsConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'apps.blogs' # 和你自己配置的应用路径保持一致

    def ready(self):
        # 导入信号模块完成注册
        import apps.blogs.signals

需要注意:你的settings.py中INSTALLED_APPS里的blogs应用要写成完整配置类路径apps.blogs.apps.BlogsConfig,否则不会执行ready方法

方案B:直接在应用__init__.py中导入

修改你贴出的apps/blogs/__init__.py,新增信号导入行:

from __future__ import absolute_import, unicode_literals
from apps.blogs.celery_files.celery import app as celery_app
# 新增下面这行导入信号
import apps.blogs.signals
__all__ = ('celery_app',)

2. 修复Celery任务逻辑

Django模型对象不能直接作为参数传递给Celery任务,序列化会失败,需要调整为传递主键,任务内部再查询对应的对象:

调整signals.py代码

from .tasks import send_mails
from apps.blogs.models import BlogPost,Subscribers
from django.db.models.signals import post_save
from django.dispatch import receiver

@receiver(post_save, sender=BlogPost)
def email_task(sender, instance, created, **kwargs):
    print(123456789)
    if created:
        subscriber_ids = list(Subscribers.objects.values_list('id', flat=True))
        # 传递主键而非模型对象
        send_mails.delay(subscriber_ids, instance.id)

调整tasks.py代码

from django.core.mail import send_mail
from travel_crm.settings import EMAIL_HOST_USER
from celery import shared_task

@shared_task
def send_mails(subscriber_ids, blog_id):
    # 模型导入放在函数内部避免循环导入
    from apps.blogs.models import BlogPost, Subscribers
    blog = BlogPost.objects.get(id=blog_id)
    subscribers = Subscribers.objects.filter(id__in=subscriber_ids)
    for user in subscribers:
        send_mail(
            'New Blog Post ', 
            f"Checkout our new blog with title {blog.title}",
            EMAIL_HOST_USER, 
            [user.email],
            fail_silently=False
        )

3. 验证效果

重启Django服务后,在admin后台新建BlogPost对象,控制台会输出你写的123456789日志,代表信号已经成功触发。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 11:12:02