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

如何修复Django REST Framework中修改密码视图的测试?

搞定DRF测试中request.data不被识别为有效元素的问题

嘿,我来帮你排查这个问题!结合你给出的视图代码,我整理了几个最常见的原因和解决办法:

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.25 02:29:38