Django POST接口测试报JSONDecodeError问题求助
问题原因
- 测试代码里用
Client.post直接传字典时,Django测试客户端默认会把数据编码成multipart/form-data格式(也就是你看到的form-data),但视图函数里用json.loads(request.body)要求请求体是JSON格式,两者不匹配导致解码失败,触发JSONDecodeError。 - 视图函数还有逻辑漏洞:调用
data.is_valid()后没做分支判断,不管验证通不通过都会执行data.save(),可能把无效数据存进数据库。
解决方案
根据需求选以下任意一种方案即可:
方案一:修改测试代码,发送JSON格式请求
在post方法里指定content_type='application/json',并把数据转成JSON字符串:
import json from django.test import TestCase, Client class TaskURLTests(TestCase): def setUp(self): self.guest_client = Client() def test_url(self): payload = {"model":"X5", "version":"LT", "serial": "DD", "created":"2023-01-01 00:00:01"} response = self.guest_client.post( '/add_robot/', data=json.dumps(payload), content_type='application/json' )
方案二:修改视图函数,适配表单格式请求(更符合Django常规写法)
Django表单类本身就适合处理form-data或urlencoded格式的数据,直接用request.POST初始化表单,同时修复验证逻辑:
from django.http import JsonResponse, HTTPStatus from .forms import RobotForm def add_robot_in_db(request): if request.method == 'POST': data = RobotForm(request.POST) if data.is_valid(): data.save() return JsonResponse(data.cleaned_data, status=HTTPStatus.CREATED) # 验证失败返回错误信息 return JsonResponse(json.loads(data.errors.as_json()), status=HTTPStatus.BAD_REQUEST) return JsonResponse({'error': 'Wrong request, only POST'}, status=HTTPStatus.BAD_REQUEST)
如果需要同时支持JSON和表单格式请求,可以让视图自动识别请求类型:
import json from django.http import JsonResponse, HTTPStatus from .forms import RobotForm def add_robot_in_db(request): if request.method == 'POST': try: # 优先处理JSON格式请求 if request.content_type == 'application/json': json_data = json.loads(request.body) data = RobotForm(json_data) else: # 处理表单格式数据 data = RobotForm(request.POST) except json.JSONDecodeError: return JsonResponse({'error': 'Invalid JSON format'}, status=HTTPStatus.BAD_REQUEST) if data.is_valid(): data.save() return JsonResponse(data.cleaned_data, status=HTTPStatus.CREATED) return JsonResponse(json.loads(data.errors.as_json()), status=HTTPStatus.BAD_REQUEST) return JsonResponse({'error': 'Wrong request, only POST'}, status=HTTPStatus.BAD_REQUEST)
内容的提问来源于stack exchange,提问作者Андрей
相关产品推荐
相关产品推荐

