JSON-encoded data alongside files in POST request is not supported

Hi,

When we need to POST a request containing a JSON-encoded body along with files, we get a `cannot encode objects that are not 2-tuples` error.

An example of such an API is https://www.pingen.com/en/developer/endpoints-documents.html, see in the `upload` tab.

```
File "/home/gbaconnier/buildout/eggs/requests-0.14.2-py2.7.egg/requests/api.py", line 98, in post
  return request('post', url, data=data, **kwargs)
File "/home/gbaconnier/buildout/eggs/requests-0.14.2-py2.7.egg/requests/safe_mode.py", line 31, in wrapped
  return function(method, url, **kwargs)
File "/home/gbaconnier/buildout/eggs/requests-0.14.2-py2.7.egg/requests/api.py", line 51, in request
  return session.request(method=method, url=url, **kwargs)
File "/home/gbaconnier/buildout/eggs/requests-0.14.2-py2.7.egg/requests/sessions.py", line 241, in request
  r.send(prefetch=prefetch)
File "/home/gbaconnier/buildout/eggs/requests-0.14.2-py2.7.egg/requests/models.py", line 532, in send
  (body, content_type) = self._encode_files(self.files)
File "/home/gbaconnier/buildout/eggs/requests-0.14.2-py2.7.egg/requests/models.py", line 358, in _encode_files
  fields = to_key_val_list(self.data)
File "/home/gbaconnier/buildout/eggs/requests-0.14.2-py2.7.egg/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
```

So I have `data` as `str` (json-encoded) and `files` being a `dict` with a `tuple`.

That's because on line 532, `self._encode_files` is called when we have `files` and in this method, at line 358, `data` is expected to not be a `str`.


Requests doesn't work this way.

You need to create your entire body yourself and provide it to 'data'.


Ok, that's done on my side. Thanks for your faster than lightning answer.


Anytime :)


Hi, I am a QA and need to automate our API's which has similar requirement. Can you please explain how to achieve it using Requests library. To be specific my requirement is I have "send" API which sends email to mentioned email id with subject and message body along with valid token as json data. This works fine but how can I send email with attachments e.g. pdf or image files using Request.
It would be of great help if you provide some working example code here as I am not a developer.
My json data looks like this
payload = {"message":{"to":"swapnil.patne@snstech.com","subject":"test msg","message":"test msg"},"elementToken":"some-valid-token"}
r = requests.post("https://some-server.com/send", data={'data': json.dumps(payload), 'file': open('logo.png')})

Thanks in advance
Swapnil


@swapnilpatne The answer depends entirely on how the upstream API expects the data to be delivered. Most likely it wants multipart data. If that's the case, Requests does not provide an easy abstraction for this use case. You'd need to build the correct multipart body yourself and provide it as opaque data for Requests to send.

Unfortunately, providing advice on how to do this is quite a bit beyond the scope of this bug tracker. =) May I recommend asking the question at Stack Overflow, or attempting to contact someone in our IRC chatroom?


Thanks for quick response, yes it expects multipart data. I will post my query on Stack Overflow
Thanks again :)