为何Django的client.post会将参数值嵌套在列表中?
Django API单元测试中request.POST参数值为列表的原因及解决办法
原因
- Django测试客户端默认行为:调用
self.client.post()并直接传入字典时,客户端会将数据以application/x-www-form-urlencoded(表单提交)格式发送。Django的request.POST是QueryDict类型,该类型设计为支持同一参数名传递多个值(如表单复选框场景),因此会将每个参数的值存储为列表。 - 前端提交的差异:如果前端采用
application/json格式提交数据,DRF会将JSON解析到request.data中,此时数据是普通Python字典,值不会被包装为列表(除非JSON本身定义为列表)。你前端测试时大概率用的是JSON提交,因此未观察到列表结构。
解决办法
方式一:模拟前端JSON提交
给测试请求指定content_type='application/json',并将数据转为JSON字符串发送,这样视图中通过request.data获取的数据和前端提交的结构完全一致:
import json result = self.client.post(reverse(path), json.dumps({"arg1":"value"}), content_type='application/json')
方式二:使用QueryDict的取值方法
如果仍需保持表单格式提交,可通过QueryDict的get()方法直接获取单个值(默认返回列表第一个元素):
arg1 = request.POST.get('arg1') # 得到"value"而非["value"]
也可以直接通过键取值,QueryDict的__getitem__方法在参数只有一个值时会返回该值而非列表(若存在多个值则返回最后一个):
arg1 = request.POST['arg1']
内容的提问来源于stack exchange,提问作者Gavin Ray
相关产品推荐
相关产品推荐

