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

使用Celery发送Djoser重置密码邮件时的序列化问题求解

解决Djoser重置密码异步邮件的Request序列化问题

核心问题是不能直接传递整个Django Request对象给Celery任务,因为Request包含大量不可序列化的属性(如IO流、底层连接实例),不管用JSON还是pickle都无法处理。正确的做法是从Request中提取任务必需的信息,只传递这些序列化友好的数据。

具体解决方案步骤

1. 重写reset_password方法,提取关键参数

在自定义的UserViewSet中,不要把Request传给Celery任务,而是提取出邮件发送需要的核心数据:

from djoser.views import UserViewSet
from celery import shared_task

class CustomUserViewSet(UserViewSet):
    def reset_password(self, request, *args, **kwargs):
        # 执行原逻辑完成密码重置核心操作
        response = super().reset_password(request, *args, **kwargs)
        
        # 从请求中提取必要信息,而非传递整个request
        user = self.get_object()
        site_domain = request.get_host()
        protocol = 'https' if request.is_secure() else 'http'
        language_code = request.LANGUAGE_CODE
        
        # 调用Celery任务,传递提取后的参数
        send_reset_password_email.delay(
            user_id=user.id,
            site_domain=site_domain,
            protocol=protocol,
            language_code=language_code
        )
        
        return response

2. 编写Celery任务,基于提取的参数生成邮件

任务中通过user_id重新获取用户实例,再用提取的域名、协议等信息构建重置链接:

from django.contrib.auth import get_user_model
from django.core.mail import send_mail
from django.utils.translation import activate
from djoser import utils

User = get_user_model()

@shared_task
def send_reset_password_email(user_id, site_domain, protocol, language_code):
    # 激活对应语言环境,保证邮件内容本地化
    activate(language_code)
    
    user = User.objects.get(id=user_id)
    # 生成重置密码令牌
    token = utils.generate_token(user)
    # 构建重置链接
    reset_url = f"{protocol}://{site_domain}/password/reset/confirm/{user.id}/{token}/"
    
    # 发送邮件(可复用Djoser内置邮件模板逻辑)
    send_mail(
        subject="重置你的密码",
        message=f"点击链接重置密码:{reset_url}",
        from_email=None,
        recipient_list=[user.email],
        fail_silently=False,
    )

关键说明

  • Request对象包含_io.BufferedReader这类无法被pickle序列化的IO实例,同时JSON序列化也无法处理复杂的Django对象结构,因此绝对不能直接传递。
  • 提取的参数都是字符串、整数这类基础类型,天然支持JSON序列化,完全符合Celery的任务参数要求。
  • 如果需要复用Djoser的邮件模板逻辑,可以直接调用Djoser内置的邮件发送工具类,只需要传入必要的上下文数据即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 02:05:23