Django Rest API Delete方法测试:传递book_type遇415错误如何解决?
解决Django REST API DELETE请求返回415错误的问题
你遇到的415错误是Unsupported Media Type(不支持的媒体类型),根源在于测试时传递数据的格式和DRF处理请求体的方式不匹配,下面给你两种清晰的解决方案:
原因分析
当你用Django测试客户端的self.client.delete()传递data参数时,默认会把数据编码成application/x-www-form-urlencoded(表单格式),但DRF的request.data默认只解析JSON、multipart等格式的请求体。对于DELETE请求的表单格式数据,DRF不会自动解析,既导致媒体类型不匹配报错,你也拿不到book_type参数。
方案一:改用查询参数传递(推荐,符合REST最佳实践)
REST规范里通常不建议DELETE请求携带请求体(不同服务器/代理的处理逻辑不一致),更稳妥的方式是把参数放在URL的查询字符串里:
修改ViewSet的destroy方法
把获取参数的方式从request.data改成request.query_params:
def destroy(self, request, pk=None, *args, **kwargs): book_type = request.query_params.get("book_type") if book_type is None: raise ParseError(detail="book_type is required, options are : 'global, non-global'") try: instance = self.get_object() user = self.request.user serializer = self.get_serializer(instance) # 你的其他业务逻辑... self.perform_destroy(instance) except Http404: pass return Response(status=status.HTTP_204_NO_CONTENT)
修改测试用例
把book_type作为查询参数拼到URL里:
def test_book_delete(self): # check if delete works url = f"/api/v1/books/shelfs/{1}/readers/{2}/?book_type=global" response = self.client.delete(url) self.assertEqual(response.status_code, 204)
方案二:保持请求体传递,但指定正确的Content-Type
如果你一定要用请求体传递参数,需要让测试客户端发送JSON格式的数据,并指定正确的媒体类型:
修改测试用例
导入json模块,把数据序列化为JSON字符串,同时设置content_type='application/json':
import json def test_book_delete(self): # check if delete works book_type = {'book_type': 'global'} response = self.client.delete( "/api/v1/books/shelfs/{}/readers/{}/".format(1, 2), data=json.dumps(book_type), content_type='application/json' ) self.assertEqual(response.status_code, 204)
ViewSet的destroy方法不需要修改,这样DRF就能正确解析请求体里的book_type参数了。
内容的提问来源于stack exchange,提问作者rai
相关产品推荐
相关产品推荐

