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

Django ModelViewSet单元测试报ValueError:解包值不足求助

解决Django DRF测试中GET请求的ValueError问题

你遇到的这个ValueError: not enough values to unpack (expected 2, got 1)错误,根源在于GET请求的参数传递方式错误,同时你的ViewSet逻辑也存在对GET请求参数获取的误区,下面一步步给你拆解修复:

1. 错误原因解析

测试代码的问题

DRF的APIClient.get()方法中,data参数的作用是构造URL的查询字符串(也就是?key=value这种形式),它需要接收一个字典,而你传入的是json.dumps(self.block_get_data)生成的JSON字符串。当DRF尝试把这个字符串转换成查询参数时,会把它当成一个键值对来解析,自然就会抛出“缺少值”的错误——因为字符串本身不是键值对结构。

另外,GET请求通常不会携带JSON格式的请求体,你设置content_type='application/json'对于GET请求来说是无效的,服务器端也不会从请求体里读取GET参数。

ViewSet的问题

你的TemplateView.list()方法里用了request.data['param']来获取参数,但request.data是用来获取POST/PUT等请求的请求体数据的,GET请求的参数应该从request.query_params(或者request.GET)里获取。

2. 修复步骤

第一步:修正测试代码

把测试中client.get()的data参数改成直接传字典,去掉json.dumps和content_type参数,同时修正你写错的参数传递:

def test_get_blocks(self):
    """Test get list of Block. """
    response = self.client.get(
        "/api/v1/financing-settings/template/",
        data=self.block_get_data  # 直接传字典,不要转JSON
    )
    self.assertEqual(response.status_code, 200)

def test_get_steps(self):
    """Test get list of Step. """
    response = self.client.get(
        "/api/v1/financing-settings/template/",
        data=self.step_get_data  # 修正之前传错的参数
    )
    self.assertEqual(response.status_code, 200)

def test_no_step_or_block(self):
    """Test get no list of Step or Block. """
    response = self.client.get(
        "/api/v1/financing-settings/template/",
        data=self.get_no_data
    )
    self.assertEqual(response.status_code, 204)

第二步:修正ViewSet的参数获取逻辑

把request.data['param']改成从request.query_params获取,同时修复Step查询的序列化问题:

class TemplateView(ModelViewSet):
    """ViewSet for Saving Block/ Step template."""
    def list(self, request, *args, **kwargs):
        """Get list of Block/Steps with is_process_template is equal to True."""
        param = request.query_params.get('param')  # 从查询参数获取
        if param == "block":
            _block = Block.objects.filter(is_process_template=True).values()
            return JsonResponse({"data": list(_block)}, safe=False, status=200)
        elif param == "step":
            _step = Step.objects.filter(is_process_template=True).values()  # 新增.values(),否则QuerySet无法直接转JSON
            return JsonResponse({"data": list(_step)}, safe=False, status=200)
        return Response(status=status.HTTP_204_NO_CONTENT)

3. 额外优化建议

  • 对于ModelViewSet,其实可以不用自己重写list方法,通过设置queryset和serializer_class,再结合django-filter过滤类来实现参数过滤,这样更符合DRF的规范。
  • 测试中可以用reverse函数反向解析URL代替硬编码的URL,后续URL变更时不需要修改测试代码。

内容的提问来源于stack exchange,提问作者Lutaaya Huzaifah Idris

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:20:12