如何修复Django REST Framework中修改密码视图的测试?
嘿,我来帮你排查这个问题!结合你给出的视图代码,我整理了几个最常见的原因和解决办法:
1. 测试请求没按DRF要求的格式发送
DRF的request.data需要正确的请求格式才能解析,如果你在测试时直接传字典又没设置Content-Type,大概率会导致request.data为空或者格式不对。
举个正确的测试请求写法:
import json from django.test import Client client = Client() # 先登录(因为你视图要求IsAuthenticated) client.login(username="你的测试用户名", password="测试密码") # 发送PUT请求,要转成JSON字符串+设置content_type response = client.put( "/api/change-password/", # 你的接口路径 data=json.dumps({"old_password": "原密码", "new_password": "新密码"}), content_type="application/json" )
要是你直接传data={"old_password": "..."}而不转JSON,DRF会把它当成表单数据,可能和你的序列化器期望的结构不匹配。
2. 重写put方法时没遵循DRF的标准流程
你重写了put方法,但其实UpdateAPIView本身已经封装了完善的更新逻辑,你的写法可能遗漏了关键步骤。比如你直接取self.request.user当实例,不如用DRF内置的get_object()更规范,而且序列化器实例化时最好同时传入对象实例(因为是更新操作)。
调整下你的put方法试试:
def put(self, request, *args, **kwargs): self.object = self.get_object() # 用DRF的get_object()获取当前用户对象 # 更新操作的序列化器要传入实例+数据 serializer = self.get_serializer(self.object, data=request.data) # 加上raise_exception=True,验证不通过时直接返回错误响应,方便调试 serializer.is_valid(raise_exception=True) # 复用DRF的perform_update完成保存 self.perform_update(serializer) return Response(status=200)
3. 序列化器的验证逻辑有问题
如果serializer.is_valid()返回False,一定要打印serializer.errors看看具体错在哪!这是最快定位问题的方法。比如在视图里加一行:
if not serializer.is_valid(): print(serializer.errors) # 测试时看控制台输出,或者返回错误响应 return Response(serializer.errors, status=400)
常见的坑比如:
- 序列化器里的
old_password字段没加验证逻辑,或者验证时和用户密码比对出错 new_password的长度、复杂度等规则没满足- 漏传了必填字段
4. 测试时没正确登录用户
你的视图要求IsAuthenticated,如果测试时没登录,request.user是匿名用户,后续调用self.object.check_password()肯定会失败,甚至request.data的解析也可能受影响。测试前一定要先登录用户,或者用force_authenticate强制设置:
from rest_framework.test import APIClient client = APIClient() user = UserInfo.objects.get(username="测试用户") client.force_authenticate(user=user) # 再发送PUT请求
快速调试小技巧
在视图的put方法里直接打印request.data,看看是不是你期望的内容:
def put(self, request, *args, **kwargs): print("request.data内容:", request.data) # 测试时看控制台 # 后面的逻辑...
如果打印出来是空的,那就是请求数据没被正确解析;如果有数据但验证不通过,就看序列化器的错误信息就行。
内容的提问来源于stack exchange,提问作者Mi5aka

