如何在Django的post_save中发送邮件且不阻塞表单提交?
解决Django post_save发送邮件阻塞用户操作的问题
我来帮你搞定这个异步发邮件的问题!你的代码现在有个关键问题:sync_to_async的用法不对,导致邮件还是同步执行,硬生生卡住了用户请求。咱们一步步调整,让发邮件彻底不阻塞:
问题出在哪?
你现在是直接执行了call_submssion_email(instance),再把执行结果传给sync_to_async——这相当于还是同步跑完了发邮件的逻辑,完全没用到异步的优势。另外你函数名还拼错了(call_submssion_email少了个字母),先一起修正。
修改后的完整代码
from asgiref.sync import sync_to_async import asyncio from django.db.models.signals import post_save from django.dispatch import receiver from django.core.mail import EmailMessage from .models import SubmissionDetails # 确保导入你的模型 @receiver(post_save, sender=SubmissionDetails) def create_submission_email(sender, instance, created, **kwargs): if created: # 把同步函数包装成异步任务,丢到事件循环里后台执行 asyncio.create_task( sync_to_async(call_manuscript_submission_email)(instance) ) def call_manuscript_submission_email(instance): print("Hi") message = '''Submitted with the title, <br> {0}'''.format(instance.title) subject = 'Article Submitted' to_address = 'example@gmail.com' from_address = "from@mail.example.com" msg = EmailMessage( subject, message, from_address, [to_address] ) msg.content_subtype = "html" msg.send()
核心调整说明
- 正确使用
sync_to_async:要把同步函数本身(而不是函数执行结果)传给sync_to_async,再传入参数调用,这样才会把同步逻辑放到异步线程里执行。 - 用
asyncio.create_task启动任务:这个方法会把异步任务加入事件循环,主线程(处理用户请求的线程)会直接继续往下走,不用等邮件发送完成。 - 注意运行环境:确保你的Django项目用ASGI服务器运行(比如Daphne),因为WSGI是同步环境,这种异步任务方式不会生效。你用的是带异步支持的Django 3.0,ASGI环境是前提。
额外提醒
如果需要邮件发送的可靠性(比如失败自动重试),这个轻量异步方案可能不够,这时候可以考虑用Celery、Django Q这类任务队列工具。但如果只是想解决“用户不用等邮件发完”的问题,上面的代码完全够用。
内容的提问来源于stack exchange,提问作者Amiya Behera
相关产品推荐
相关产品推荐

