Django post_save信号生产环境失效(开发环境正常)求助
1. 最可能的原因:创建时未关联用户导致信号报错
看你的创建视图代码,form.save()直接保存,但如果Navette模型的user字段是必填外键,你没有在视图里把当前登录用户赋值给实例:
# 原视图代码里的保存逻辑 if form.is_valid(): form.save() # 这里没有设置instance.user = request.user
这会导致创建的Navette实例user字段为None,而你的post_save信号里写了user = instance.user.username,访问None的username属性会直接抛出AttributeError,信号函数崩溃,邮件根本没机会发送。
而删除操作是针对已存在的记录,这些记录的user字段是有值的,所以post_delete信号能正常执行。
解决办法:修改视图的保存逻辑,手动关联当前用户:
if form.is_valid(): instance = form.save(commit=False) instance.user = request.user # 关联当前登录用户 instance.save()
2. 信号注册配置错误
你在应用的__init__.py里写了default_app_config = 'navette.apps.ActivityAppConfig',但apps.py里的类是NavetteConfig,两者不匹配,这会导致Django加载AppConfig时找不到对应的类,ready()方法不会执行,信号无法注册。虽然你说删除信号能生效,但还是建议修正配置:
把__init__.py里的配置改成:
default_app_config = 'navette.apps.NavetteConfig'
3. 邮件发送无异常捕获,报错无日志
你的alert函数没有任何异常处理,生产环境如果发送邮件时出现小问题(比如SMTP连接超时、参数错误),会直接抛出异常但没有日志,你根本不知道哪里错了。
解决办法:给alert函数加上异常捕获和日志:
import logging from django.conf import settings from django.core.mail import EmailMessage import smtplib logger = logging.getLogger(__name__) def alert(**kwargs): try: de = kwargs.get('de', 'toto@gmail.com') pour = kwargs.get('pour', 'tintin@gmail.com') sujet = kwargs.get('sujet', 'Sujet Général') contenu = kwargs.get('contenu', 'cf. objet du mail') host = 'smtp.gmail.com' port = 465 user = settings.EMAIL_HOST_USER passw = settings.EMAIL_HOST_PASSWORD msg = EmailMessage() msg['Subject'] = sujet msg['From'] = de msg['To'] = pour msg.set_content('HTML uniquement') msg.add_alternative(contenu, subtype='html') with smtplib.SMTP_SSL(host, port) as smtp: smtp.login(user, passw) smtp.send_message(msg) logger.info(f"邮件发送成功: {sujet}") except Exception as e: logger.error(f"邮件发送失败: {str(e)}", exc_info=True)
这样生产环境的日志里会清晰显示邮件发送的问题,方便排查。
4. 生产环境事务影响(概率较低)
如果生产环境用了数据库事务,post_save信号会在事务提交前触发,极端情况下如果事务后续回滚,或者邮件发送依赖未提交的数据,但你删除信号能正常工作,这个可能性不大,但可以检查是否有事务包裹了创建逻辑。
内容的提问来源于stack exchange,提问作者Abpostman1

