2

マルチパートフォームデータをサーバーに送信する RESTful API POST-verb のテストを書いています。データをjsonエンコードしたいと思います。それを行う正しい方法は何ですか?以下に 3 つのテストを示します。最初の 2 つのテストは成功し、3 つ目のテスト (必要なシナリオ) は失敗します。どんな助けでも大歓迎です。

import requests
import json

print "test 1, files+data/nojson"
requests.post('http://localhost:8080', files={'spot[photo]': open('test.jpg', 'rb')}, data={'spot': 'spot_description'})

print "test 2, only data/json"
requests.post('http://localhost:8080',data=json.dumps({'spot': 'spot_description'}))

print "test 3, only files+data/json"
requests.post('http://localhost:8080', files={'spot[photo]': open('test.jpg',
'rb')}, data=json.dumps({'spot': 'spot_description'}))

コードは次を出力します。

$ /cygdrive/c/Python27/python.exe -B test.py
test 1, files+data/nojson
test 2, only data/json
test 3, only files+data/json
Traceback (most recent call last):
  File "test.py", line 12, in <module>
    'rb')}, data=json.dumps({'spot': 'spot_description'}))
  File "C:\Python27\lib\site-packages\requests\api.py", line 98, in post
    return request('post', url, data=data, **kwargs)
  File "C:\Python27\lib\site-packages\requests\safe_mode.py", line 39, in wrapped
    return function(method, url, **kwargs)
  File "C:\Python27\lib\site-packages\requests\api.py", line 51, in request
    return session.request(method=method, url=url, **kwargs)
  File "C:\Python27\lib\site-packages\requests\sessions.py", line 241, in request
    r.send(prefetch=prefetch)
  File "C:\Python27\lib\site-packages\requests\models.py", line 532, in send
    (body, content_type) = self._encode_files(self.files)
  File "C:\Python27\lib\site-packages\requests\models.py", line 358, in _encode_files
    fields = to_key_val_list(self.data)
  File "C:\Python27\lib\site-packages\requests\utils.py", line 157, in to_key_val_list
    raise ValueError('cannot encode objects that are not 2-tuples')
ValueError: cannot encode objects that are not 2-tuples
4

2 に答える 2

2

エラーは、dataパラメーターが文字列であるためです。

models.py::send():

    # Multi-part file uploads.
    if self.files:
        (body, content_type) = self._encode_files(self.files)

models.py::_encode_files():

    fields = to_key_val_list(self.data)
    files = to_key_val_list(files)

utils.py::to_key_val_list()

if isinstance(value, (str, bytes, bool, int)):
    raise ValueError('cannot encode objects that are not 2-tuples')

これは、self.data を使用した呼び出しでヒットしています。辞書の文字列表現を渡していますが、次のように辞書自体が必要です。

requests.post('http://localhost:8080',
              files={'spot[photo]': open('test.jpg', 'rb')},
              data={'spot': 'spot_description'})

そのため、ファイル パラメータに何かが割り当てられている場合、データ パラメータは str、bytes、bool、または int 型にすることはできません。ソース コードをたどることができます: https://github.com/kennethreitz/requests/blob/master/requests/models.py#L531

于 2012-12-05T20:12:57.083 に答える
1

POSTJSON データは、次のようにフォーム エンコードされたフィールドに埋め込むことで回避できます。

post(url, data={'data': json.dumps(actual_data)}, files={'myfile': open('foo.data')})

また、次のようにすべてを入れることができると思いますfiles

post(url, files={'data': json.dumps(actual_data), 'myfile': open('foo.dat')})

...これは最初のスニペットと同等である必要があります。

于 2013-03-17T22:59:39.443 に答える