【问题标题】:Can't POST file attachment and data parameters with Python requests lib无法使用 Python 请求库发布文件附件和数据参数
【发布时间】:2013-10-29 12:49:50
【问题描述】:

我正在尝试实现一个简单的 Django 视图,它接受文件附件和其他一些参数,并在远程 API 调用上代理请求。

请注意:代理不是我的问题的重点:)

这就是我实现视图的方式:

def image_upload(request):
    token = request.POST['token']
    image_file = request.FILES.values()[0]

    files = {'file': ('myupload.txt', image_file.read())}

    client_id = request.POST['client_id']
    folder_id = request.POST['folder_id']
    advert_id = request.POST['advert_id']
    image_type = request.POST['image_type']
    crop_image = request.POST['crop_image']

    api_base_url = settings.API_BASE_URL

    file_post_data = {'client_id': client_id, 'folder_id': folder_id, 'advert_id': advert_id,
            'image_type': image_type, 'crop_image': crop_image}

    auth_header = {'Authorization': 'Token ' + token}

    r = requests.post(api_base_url + 'assets/image/upload/', 
        data = json.dumps(file_post_data), 
        headers = auth_header,
        files = files)

    return r.json()

问题是,当我测试这个视图时(我使用 Django 测试客户端来做),我在“files = files)”行收到一个错误,上面写着“ValueError: cannot encode objects that are not 2 -元组”。

完整的跟踪日志是这个:

======================================================================
ERROR: test_image_upload (fbx.tests.FbxTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/andrea/Documents/src/fbxapp/onboard/fbx/tests.py", line 18, in test_image_upload
    'image_type': 'A', 'crop_image': False, 'attachment': fp})
  File "/usr/local/lib/python2.7/dist-packages/django/test/client.py", line 449, in post
    response = super(Client, self).post(path, data=data, content_type=content_type, **extra)
  File "/usr/local/lib/python2.7/dist-packages/django/test/client.py", line 262, in post
    return self.request(**r)
  File "/usr/local/lib/python2.7/dist-packages/django/core/handlers/base.py", line 111, in get_response
    response = callback(request, *callback_args, **callback_kwargs)
  File "/home/andrea/Documents/src/fbxapp/onboard/fbx/views.py", line 42, in image_upload
    files = files)
  File "/usr/local/lib/python2.7/dist-packages/requests/api.py", line 88, in post
    return request('post', url, data=data, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/api.py", line 44, in request
    return session.request(method=method, url=url, **kwargs)
  File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 324, in request
    prep = req.prepare()
  File "/usr/local/lib/python2.7/dist-packages/requests/models.py", line 225, in prepare
    p.prepare_body(self.data, self.files)
  File "/usr/local/lib/python2.7/dist-packages/requests/models.py", line 385, in prepare_body
    (body, content_type) = self._encode_files(files, data)
  File "/usr/local/lib/python2.7/dist-packages/requests/models.py", line 99, in _encode_files
    fields = to_key_val_list(data or {})
  File "/usr/local/lib/python2.7/dist-packages/requests/utils.py", line 136, in to_key_val_list
    raise ValueError('cannot encode objects that are not 2-tuples')
ValueError: cannot encode objects that are not 2-tuples

我还尝试使用它来读取文件的快速测试:files = {'file': ('myupload.txt', open('/tmp/mytmp.txt', 'rb') )}

但它不起作用。你知道如何解决这个问题吗?

谢谢!

【问题讨论】:

  • w files = {'file': image_file.open('/tmp/mytmp.txt', 'rb')}...注意没有多余的 ()

标签: python django python-requests


【解决方案1】:

您不能同时发布 JSON 数据和 multipart/form-data,这实际上是您在此处尝试执行的操作。 json.dumps 返回一个字符串,因此您发送的字符串看起来像

'{"client_id": 1, "folder_id": 2, "advert_id": 3, "image_type": "jpeg", "crop_image": true}'

然后通过files 参数发送一些东西来告诉请求你想将它与multipart/form-data 请求结合使用。这是不可能的,可能会引发更好的例外。

要么将文件读入内存后将其添加到 JSON 数据中,然后使用适当的 Content-Type 标头发送,要么将整个内容作为 multipart/form-data 请求发送没有,使用 json.dumps 和只需将您正在创建的字典传递给data。使用其中一种,但不能同时使用。

除此之外,您说您的异常来自仅包含 files=files) 的行,但导致异常的不仅仅是该行。该异常由恰好在该行结束的函数引发。您的例外也由此产生的事实仅仅是巧合。这是 Python 中的一个缺陷,可能在 Python 3.4 中得到修复。你应该升级,因为 3.4 会很棒而且新版本的 Django 支持 Python 3.x。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多