Django重置密码:从忘记密码视图取邮箱,无需用户重复输入
问题分析
报错cannot access local variable 'email' where it is not associated with a value的核心原因是:在ChangePasswordView的post方法中,你在未定义email变量的情况下就用它查询数据库,同时当前代码还在从请求里获取邮箱,完全不符合“修改密码无需输入邮箱”的需求。
正确逻辑应该是:通过URL传递的token找到对应用户,直接从用户对象中提取邮箱,不需要前端传邮箱参数。
修复方案
- 调整
ChangePasswordView的方法参数,只接收token(需同步修改URL配置,将token作为路径参数) - 通过
token直接关联用户,而非依赖请求中的邮箱 - 移除所有从请求中获取邮箱的代码,从用户对象中提取所需信息
- 密码修改完成后清空令牌,避免重复使用
修改后的完整代码
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
相关产品推荐
相关产品推荐

