12

我正在使用 django REST 框架构建一个 API。

为了测试这个 API,我正在使用 pytest 和测试客户端,如下所示:

def test_doesnt_find(self, client):
    resp = client.post(self.url, data={'name': '123'})
    assert resp.status_code == 404

或者

def test_doesnt_find(self, client):
    resp = client.get(self.url, data={'name': '123'})
    assert resp.status_code == 404

在使用 REST 框架的通用 GET、POST 和 DELETE 类时都可以工作(例如DestroyAPIViewRetrieveUpdateAPIView或仅APIView使用 get 和 post 函数)

我遇到问题的地方是使用 PATCH 和 PUT 视图时。比如RetrieveUpdateAPIView。在这里我突然不得不使用:

resp = client.patch(self.url, data="name=123", content_type='application/x-www-form-urlencoded')

或者

resp = client.patch(self.url, data=json.dumps({'name': '123'}), content_type='application/json')

如果我只是尝试像以前那样使用测试客户端,我会收到错误:

rest_framework.exceptions.UnsupportedMediaType: Unsupported media type "application/octet-stream" in request.

当我在 client.patch() 调用中指定 'application/json' 时:

rest_framework.exceptions.ParseError: JSON parse error - Expecting property name enclosed in double quotes: line 1 column 2 (char 1)`

谁能向我解释这种行为?由于 curl 简单地使用-X PATCH -d"name=123".

4

3 回答 3

16

rest_framework.exceptions.ParseError:JSON 解析错误 - 期望用双引号括起来的属性名称:第 1 行第 2 列(字符 1)`

这通常表明您在 json 中的字符串中发送了一个字符串。例如:

resp = client.patch(self.url, data=json.dumps("name=123"), content_type='application/json')

会导致此类问题。

rest_framework.exceptions.UnsupportedMediaType:请求中不支持的媒体类型“application/octet-stream”。

这意味着请求已作为“application/octet-stream”发送,这是 Django 的测试默认值。

为了减轻处理这一切的痛苦,Django REST 框架自己提供了一个客户端:http: //www.django-rest-framework.org/api-guide/testing/#apiclient

请注意,该语法与 Django 的语法略有不同,您不必处理 json 编码。

于 2016-10-10T08:11:17.790 回答
0

至于带有 JSON 数据的请求,由于JSON 语法,您收到此错误,它需要在字符串上加上双引号。

于 2016-10-07T18:06:08.873 回答
0

Pytest 使用 django 测试客户端和client.post默认 content_type 是multipart/form-data,而putpatchdelete使用application/octet-stream

这就是为什么有时这很棘手。即使是发布请求,如果您计划支持 JSON 有效负载,您必须在测试请求中告知内容类型。无论如何,使用最新的 Django 版本,您只需将数据对象传递给客户端请求,它将为您序列化,如文档中所述:

如果您将 content_type 提供为 application/json,则如果数据是 dict、list 或 tuple,则使用 json.dumps() 对数据进行序列化。默认情况下,使用 DjangoJSONEncoder 执行序列化,并且可以通过向 Client 提供 json_encoder 参数来覆盖。put()、patch() 和 delete() 请求也会发生这种序列化。

例如:

resp = client.patch(self.url, {'name': '123'}, content_type='application/json')
于 2020-07-17T14:29:22.640 回答