Django 从 0 到 1 打造完整电商平台:使用 Celery 异步发送邮件/短信
IT策士 10余年一线大厂经验专注 IT 思维、架构、职场进阶。我也会在其它的平台持续发布最新文章助你少走弯路。系列写到这里我们电商平台的核心业务已经跑通用户注册、商品浏览、购物车、下单、支付、订单管理。但有一个体验问题一直存在——发送邮件和短信是在主请求线程里同步执行的。也就是说用户注册时点击提交后端要等邮件发完哪怕只是写到控制台才返回响应下单成功后也要等短信发送完毕。这在开发阶段看不出来但到了生产环境网络延迟或邮件服务器慢都会让用户多等好几秒严重影响体验。解决这个问题的标准做法是把耗时的 IO 操作从主线程剥离交给异步任务队列处理。Django 生态中最成熟的选择就是Celery。今天我们就来给项目装上 Celery改造邮件和短信的发送逻辑让它们真正“后台运行”前端秒级响应。一、为什么选择 Celery Redis1.1 什么是 CeleryCelery 是一个基于 Python 的分布式任务队列框架。它的核心概念工作流程视图 → 把任务放入 Broker → Worker 取出执行 → 视图立刻返回无需等待。1.2 为什么选 Redis 做 Broker我们的项目第 24 篇还会用 Redis 做缓存一举两得Redis 轻量级学习成本低开发环境完全够用生产环境中小规模也足够。二、安装 Redis 和 Celery2.1 安装 RedismacOSbrewinstallredis brew services start redisUbuntu/Debiansudoaptupdatesudoaptinstallredis-serversudosystemctl start redisWindows从 Redis for Windows 下载 msi 安装包安装后会自动启动服务。验证 Redis 是否启动控制台输出如果返回PONG说明 Redis 正常运行。2.2 安装 Celery进入项目虚拟环境pipinstallcelery[redis]这条命令会同时安装 Celery 和它所需的 Redis 客户端依赖。控制台输出Collecting celery[redis]Downloading celery-5.3.x-py3-none-any.whl... Successfully installed celery-5.3.x...验证安装控制台输出三、配置 Celery3.1 创建 celery.py在项目配置目录django_ecommerce/下新建celery.pyimportos from celeryimportCelery# 设置 Django 的默认 settings 模块os.environ.setdefault(DJANGO_SETTINGS_MODULE,django_ecommerce.settings)appCelery(django_ecommerce)# 从 Django settings 中加载 Celery 配置所有配置项以 CELERY_ 开头app.config_from_object(django.conf:settings,namespaceCELERY)# 自动发现所有已注册 app 下的 tasks.py 文件app.autodiscover_tasks()3.2 修改init.py编辑django_ecommerce/__init__.py确保 Django 启动时加载 Celeryfrom .celeryimportapp as celery_app __all__(celery_app,)3.3 在 settings.py 中增加 Celery 配置在django_ecommerce/settings.py末尾添加# Celery 配置 # Redis 作为消息代理CELERY_BROKER_URLredis://127.0.0.1:6379/0# 结果存储后端可选CELERY_RESULT_BACKENDredis://127.0.0.1:6379/1# 接受的内容类型CELERY_ACCEPT_CONTENT[json]# 序列化方式CELERY_TASK_SERIALIZERjson# 结果序列化方式CELERY_RESULT_SERIALIZERjson# 时区CELERY_TIMEZONEAsia/Shanghai四、创建异步任务按照 Celery 的约定任务函数应该放在各 app 下的tasks.py文件中。Celery 的autodiscover_tasks会自动扫描。4.1 发送邮件任务在apps/users/tasks.py中创建如果还没有该文件就新建from celeryimportshared_task from django.core.mailimportsend_mail from django.confimportsettings shared_task(bindTrue,max_retries3,default_retry_delay60)def send_activation_email_task(self, user_id, activation_url, recipient_email): 异步发送激活邮件 try: send_mail(subject激活你的电商账号,messagef点击链接激活账号{activation_url},from_emailnoreplyexample.com,recipient_list[recipient_email],)except Exception as e:# 发送失败自动重试raise self.retry(exce)shared_task def send_order_notification_email_task(user_email, order_no, total_amount): 下单成功后异步发送通知邮件 send_mail(subjectf订单 {order_no} 已生成,messagef您的订单 {order_no}金额¥{total_amount}已生成请尽快支付。,from_emailnoreplyexample.com,recipient_list[user_email],)参数说明bindTrue绑定任务实例到self用于调用self.retry()实现失败重试。max_retries3最多重试 3 次。default_retry_delay60每次重试间隔 60 秒。4.2 发送短信任务在apps/users/tasks.py中继续添加importlogging loggerlogging.getLogger(users)shared_task def send_sms_task(phone, code): 异步发送短信验证码模拟 生产环境对接阿里云/腾讯云短信服务# 模拟发送实际换成 API 调用logger.info(f[异步短信] 向 {phone} 发送验证码{code})# 这里可以调用真实的短信 SDK# 例如send_sms(phone, code)returnfSMS sent to {phone}五、改造视图改为异步调用现在我们要把之前视图里同步发送邮件/短信的地方全部替换为调用 Celery 任务。5.1 注册视图——异步发送激活邮件和短信编辑apps/users/views.py找到register函数修改邮件发送部分from .tasksimportsend_activation_email_task, send_sms_task def register(request):# ... 表单验证和用户创建逻辑不变 ...ifemail:# 原来send_mail(...)# 现在调用异步任务tokenstr(random.randint(100000,999999))request.session[femail_token_{user.id}]token activate_urlrequest.build_absolute_uri(f/users/activate/{user.id}/{token}/)send_activation_email_task.delay(user.id, activate_url, email)messages.success(request,注册成功激活邮件已发送请前往邮箱查收。)之前发送短信验证码的视图send_sms_code也可以改为异步但注意验证码需要存储到 session我们保留同步写 session只把“发送”动作异步require_POST def send_sms_code(request): phonerequest.POST.get(phone)# ... 生成验证码逻辑 ...request.session[sms_code]code request.session.set_expiry(300)# 异步发送短信send_sms_task.delay(phone, code)returnJsonResponse({ok:True,msg:验证码已发送异步})5.2 下单视图——异步发送通知邮件编辑apps/orders/views.py找到order_submit视图在订单创建成功后添加通知邮件任务from users.tasksimportsend_order_notification_email_task# 在 order_submit 中的订单创建成功后send_order_notification_email_task.delay(user.email, order.order_no, float(order.total_amount))如果用户没有邮箱可以先判断ifuser.email: send_order_notification_email_task.delay(user.email, order.order_no, float(order.total_amount))5.3 确保邮件配置当前开发环境仍使用控制台后端我们可以在 settings.py 中临时添加一个真实的 SMTP 配置来测试异步效果比如使用 QQ 邮箱、163 邮箱的 SMTP。如果不想配真邮箱控制台后端依然有效只是你会看到 Worker 的控制台打印邮件内容而不再是 Django 主进程打印。六、启动 Celery Worker 并测试6.1 启动 Redis如果尚未启动确保 Redis 服务运行中。6.2 启动 Celery Worker在项目根目录打开一个新的终端窗口激活虚拟环境后执行celery-Adjango_ecommerce worker-linfo控制台输出示例-------------- celeryMacBook-Pro.local v5.3.x --- ***** ----- -- ******* ---- Linux-6.1.0 x86_64 - *** --- * --- - ** ----------[config]- ** ---------- .app: django_ecommerce:0x... - ** ---------- .transport: redis://127.0.0.1:6379/0 - ** ---------- .results: redis://127.0.0.1:6379/1 - *** --- * --- .concurrency:8(prefork)-- ******* ---- .task events: OFF --- ***** ----- --------------[queues].celeryexchangecelery(direct)keycelery[tasks].users.tasks.send_activation_email_task.users.tasks.send_sms_task.users.tasks.send_order_notification_email_task看到了三个任务已经被 Worker 发现并注册。6.3 测试注册激活邮件启动 Django 开发服务器在另一个终端python manage.py runserver访问注册页填写邮箱testexample.com并提交。Django 主进程终端显示请求处理但不再打印邮件内容。观察 Celery Worker 终端会看到任务执行日志[2026-05-2610:15:30,123: INFO/ForkPoolWorker-1]users.tasks.send_activation_email_task[abc123]: 邮件已发送... MIME-Version:1.0Subject: 激活你的电商账号...对比之前同步发送时runserver终端会打印邮件现在异步后邮件发送转移到了 Worker 终端Django 主线程秒级返回。6.4 测试短信验证码点击“获取验证码”Django 终端显示请求Worker 终端显示[2026-05-2610:18:22,456: INFO/ForkPoolWorker-1][异步短信]向13800138000发送验证码3847296.5 测试下单通知邮件完成一笔下单流程购物车 → 确认订单 → 提交订单。订单创建成功后Worker 终端输出订单通知邮件的发送内容。七、常见问题与排错7.1 Celery Worker 启动报错ModuleNotFoundError确保你的项目路径在 Python 搜索路径中并且启动命令在项目根目录有manage.py的那一级执行。如果apps模块找不到检查sys.path.insert是否在settings.py中正确配置。7.2 任务未被 Worker 执行检查celery.py中app.autodiscover_tasks()是否调用且 tasks.py 文件名是否正确注意复数tasks。7.3 Redis 连接失败检查 Redis 是否启动redis-cli ping。如果 Redis 设置了密码CELERY_BROKER_URL格式为redis://:password127.0.0.1:6379/0。八、总结与下集预告今天我们为电商项目注入了异步能力安装配置了 Redis Celery创建了异步发送邮件和短信的任务支持失败重试改造了注册、短信、下单视图将耗时操作异步化成功启动了 Celery Worker完成了异步任务的端到端测试。现在用户操作的响应速度大幅提升系统吞吐量也更高。下一步我们将利用 Redis 的另一个强大功能——缓存优化。第 24 篇我会带你为商品列表、详情页加上 Redis 缓存让频繁访问的商品数据不再每次都查数据库性能再上新台阶。想了解也可以去其它平台搜索「IT策士」一起升级 IT 思维 本文为《Django 从 0 到 1 打造完整电商平台》系列第 23 篇。