我正在尝试实现一个简单的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 Test Client来做)我在“files = files”行上出现错误,上面写着“ ValueError:无法编码不是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') )}
但它不起作用。有没有想过如何解决这个问题?
谢谢!
答案 0 :(得分:3)
你不能同时发布JSON数据和multipart/form-data
,这实际上是你在这里尝试做的。 json.dumps
返回一个字符串,因此您发送的字符串看起来像
'{"client_id": 1, "folder_id": 2, "advert_id": 3, "image_type": "jpeg", "crop_image": true}'
然后通过multipart/form-data
参数发送内容,告诉您要将其与files
请求结合使用的请求。这是不可能的,可能会引发更好的例外。
将文件读入内存后将文件添加到JSON数据中并使用相应的Content-Type
标头发送,或将整个内容作为multipart/form-data
请求发送,而不使用 json.dumps
只需将您创建的词典传递给data
即可。使用其中一个但不是两个。
除此之外,你说你的异常来自只有files=files)
的行,但不是那个行导致异常。函数引发异常,该函数恰好在该行结束。你的例外也因此而产生的事实仅仅是巧合。这是Python中的一个疣,可能在Python 3.4中修复。你应该升级,因为3.4会很棒,而较新版本的Django支持Python 3.x。