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

Django测试:如何通过client.post传递嵌套字典参数

Django测试客户端POST嵌套字典丢失数据的解决方法

问题场景

我有一个嵌套字典A,包含字典类型的值B:

B = {"k1": "v1", "k2": "v2", "k3": "v3",}
A = {"User": B}

这个字典用于Django视图函数中:

def views_function(request):
   # 期望request.data是和A结构一致的嵌套字典

我基于django.test.TestCase编写单元测试时,发现测试客户端无法正确传递嵌套字典:

from django.test import TestCase

class test_cases(TestCase):
    
    def setUp(self):
        self.B = {"k1": "v1", "k2": "v2", "k3": "v3",}
        self.A = {"User": self.B}
        self.url = reverse("views_function_url")

    def test_views_function(self):
        response = self.client.post(url, self.A, format="json")

测试函数里打印A是正常的,但视图中打印request.data.dict()时,只得到{'User': 'k3'},嵌套字典的其他键值对都丢失了。

问题原因

这是因为原生Django测试客户端的post方法默认使用表单编码(application/x-www-form-urlencoded)处理数据,这种编码格式不支持嵌套结构。它会把User对应的嵌套字典B拆解成User=k1&User=k2&User=k3的形式,而表单编码中同一个键重复出现时,只会保留最后一个值,所以最终User的值只剩下k3。

另外,原生Django测试客户端并不识别format="json"参数,所以即使加了这个参数,也不会自动把字典序列化为JSON格式。

解决方法

方法1:手动序列化JSON并指定Content-Type

使用json模块把嵌套字典序列化为JSON字符串,然后在post请求中明确指定content_type='application/json':

import json
from django.test import TestCase

class test_cases(TestCase):
    
    def setUp(self):
        self.B = {"k1": "v1", "k2": "v2", "k3": "v3",}
        self.A = {"User": self.B}
        self.url = reverse("views_function_url")

    def test_views_function(self):
        # 将嵌套字典转为JSON字符串
        json_payload = json.dumps(self.A)
        # 发送POST请求,指定Content-Type为application/json
        response = self.client.post(self.url, json_payload, content_type='application/json')

方法2:使用DRF的APIClient(如果项目用了DRF)

如果你的项目基于Django REST Framework(DRF)开发,可以直接使用DRF提供的APIClient,它支持format="json"参数,能自动处理嵌套字典的序列化:

from rest_framework.test import APIClient
from django.test import TestCase

class test_cases(TestCase):
    def setUp(self):
        # 替换原生client为DRF的APIClient
        self.client = APIClient()
        self.B = {"k1": "v1", "k2": "v2", "k3": "v3",}
        self.A = {"User": self.B}
        self.url = reverse("views_function_url")

    def test_views_function(self):
        # format="json"会自动将嵌套字典序列化为JSON
        response = self.client.post(self.url, self.A, format="json")

验证修改

修改后,在视图函数中直接访问request.data(如果是DRF的Request对象),就能得到完整的嵌套字典:

def views_function(request):
    print(request.data)  # 输出: {"User": {"k1": "v1", "k2": "v2", "k3": "v3"}}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 23:26:05