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 クラスを使用する場合に機能します (DestroyAPIViewまたはRetrieveUpdateAPIView単にAPIViewget および 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」。

これは、リクエストが Django のテスト デフォルトである「application/octet-stream」として送信されたことを意味します。

これらすべてを処理する手間を軽減するために、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ですが、putpatch、およびdeleteapplication/octet-streamを使用します。

そのため、これは時々トリッキーです。post リクエストでも、JSON ペイロードをサポートする予定がある場合は、テスト リクエストでコンテンツ タイプを指定する必要があります。とにかく、最近の Django バージョンでは、データ オブジェクトをクライアント リクエストに渡すだけで、docsで宣言されているようにシリアル化されます。

content_type を application/json として指定すると、辞書、リスト、またはタプルの場合、データは json.dumps() を使用してシリアル化されます。シリアル化はデフォルトで DjangoJSONEncoder で実行され、クライアントに json_encoder 引数を提供することでオーバーライドできます。このシリアライゼーションは、put()、patch()、および delete() リクエストでも発生します。

例えば:

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