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

Django重置密码:从忘记密码视图取邮箱,无需用户重复输入

问题分析

报错cannot access local variable 'email' where it is not associated with a value的核心原因是:在ChangePasswordView的post方法中,你在未定义email变量的情况下就用它查询数据库,同时当前代码还在从请求里获取邮箱,完全不符合“修改密码无需输入邮箱”的需求。

正确逻辑应该是:通过URL传递的token找到对应用户,直接从用户对象中提取邮箱,不需要前端传邮箱参数。

修复方案
  1. 调整ChangePasswordView的方法参数,只接收token(需同步修改URL配置,将token作为路径参数)
  2. 通过token直接关联用户,而非依赖请求中的邮箱
  3. 移除所有从请求中获取邮箱的代码,从用户对象中提取所需信息
  4. 密码修改完成后清空令牌,避免重复使用
修改后的完整代码
class ChangePasswordView(APIView):
    def get(self, request, token):
        context = {}
        try:
            profile_obj = UserAccount.objects.filter(forget_password_token=token).first()
            if profile_obj:
                context['email'] = profile_obj.email
                return JsonResponse(context)
            else:
                return JsonResponse({'message': 'Invalid token.'}, status=400)
        except Exception as e:
            print(e)
            return JsonResponse({'message': 'An error occurred.'}, status=500)

    def post(self, request, token):
        try:
            # 通过token定位用户
            user_obj = UserAccount.objects.filter(forget_password_token=token).first()
            if not user_obj:
                return JsonResponse({'message': 'Invalid token.'}, status=400)
            
            new_password = request.data.get('new_password')
            confirm_password = request.data.get('reconfirm_password')

            # 基础参数校验
            if not new_password or not confirm_password:
                return JsonResponse({'message': 'Please provide both new password and confirm password.'}, status=400)
            if new_password != confirm_password:
                return JsonResponse({'message': 'Both passwords should be equal.'}, status=400)
            
            # 修改密码并清空令牌
            user_obj.set_password(new_password)
            user_obj.forget_password_token = ""  # 防止令牌重复使用
            user_obj.save()
            return JsonResponse({'message': 'Password changed successfully.'})

        except Exception as e:
            print(e)
            return JsonResponse({'message': 'An error occurred.'}, status=500)


@method_decorator(csrf_exempt, name='dispatch')
class ForgetPasswordView(View):
    def post(self, request):
        try:
            data = json.loads(request.body)
            email = data.get('email')
            if not email or not UserAccount.objects.filter(email=email).exists():
                return JsonResponse({'message': 'No user found with this email.'}, status=400)

            user_obj = UserAccount.objects.get(email=email)
            token = str(uuid.uuid4())
            user_obj.forget_password_token = token
            user_obj.save()
            send_forget_password_mail(user_obj.email, token)
            return JsonResponse({'message': 'An email has been sent.'})

        except Exception as e:
            print(e)
            return JsonResponse({'message': 'An error occurred.'}, status=500)

        return JsonResponse({'message': 'Something went wrong.'}, status=500)
关键修改说明
  • 移除了ChangePasswordView方法中的email参数,完全通过token关联用户
  • 新增密码参数非空校验,提升接口鲁棒性
  • 密码修改后清空forget_password_token,避免令牌被恶意重复利用
  • 给所有响应添加了符合REST规范的HTTP状态码

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 09:57:52