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
相关产品推荐
相关产品推荐

