如何使用 rest_framework.test.APITestCase 发送多个文件
How to send multiple files using rest_framework.test.APITestCase
我正在尝试将几个文件发送到我的后端:
class AccountsImporterTestCase(APITestCase):
def test(self):
data = [open('accounts/importer/accounts.csv'), open('accounts/importer/apartments.csv')]
response = self.client.post('/api/v1/accounts/import/', data, format='multipart')
self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED)
但是我收到一个错误:
Error
Traceback (most recent call last):
File "/vagrant/conjuntos/accounts/tests/cases.py", line 128, in test
response = self.client.post('/api/v1/accounts/import/', data, format='multipart')
File "/vagrant/venv/lib/python3.4/site-packages/rest_framework/test.py", line 168, in post
path, data=data, format=format, content_type=content_type, **extra)
File "/vagrant/venv/lib/python3.4/site-packages/rest_framework/test.py", line 89, in post
data, content_type = self._encode_data(data, format, content_type)
File "/vagrant/venv/lib/python3.4/site-packages/rest_framework/test.py", line 64, in _encode_data
ret = renderer.render(data)
File "/vagrant/venv/lib/python3.4/site-packages/rest_framework/renderers.py", line 757, in render
return encode_multipart(self.BOUNDARY, data)
File "/vagrant/venv/lib/python3.4/site-packages/django/test/client.py", line 156, in encode_multipart
for (key, value) in data.items():
AttributeError: 'list' object has no attribute 'items'
我知道我没有正确准备数据,但可以这样做吗?如何做?。谢谢!
更新: 尝试@Kevin Brown 解决方案
def test(self):
data = QueryDict('', mutable=True)
data.setlist('files', [open('accounts/importer/accounts.csv'), open('accounts/importer/apartments.csv')])
response = self.client.post('/api/v1/accounts/import/', data, format='multipart')
self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED)
得到以下内容:
Error
Traceback (most recent call last):
File "/vagrant/conjuntos/accounts/tests/cases.py", line 130, in test
response = self.client.post('/api/v1/accounts/import/', data, format='multipart')
File "/vagrant/venv/lib/python3.4/site-packages/rest_framework/test.py", line 168, in post
path, data=data, format=format, content_type=content_type, **extra)
File "/vagrant/venv/lib/python3.4/site-packages/rest_framework/test.py", line 89, in post
data, content_type = self._encode_data(data, format, content_type)
File "/vagrant/venv/lib/python3.4/site-packages/rest_framework/test.py", line 64, in _encode_data
ret = renderer.render(data)
File "/vagrant/venv/lib/python3.4/site-packages/rest_framework/renderers.py", line 757, in render
return encode_multipart(self.BOUNDARY, data)
File "/vagrant/venv/lib/python3.4/site-packages/django/test/client.py", line 182, in encode_multipart
return b'\r\n'.join(lines)
TypeError: sequence item 4: expected bytes, bytearray, or an object with the buffer interface, str found
检查这是否解决了您的问题,因为从错误中可以清楚地看出数据不应该是 list
data = {"account_csv": open('accounts/importer/accounts.csv'), "apartments_csv": open('accounts/importer/apartments.csv')}
这个 link 你可能会觉得有用 Uploading multiple files in a single request using python requests module
您正在向视图发送文件列表,但发送不正确。当您将数据发送到视图时,无论是 Django 视图还是 DRF 视图,您都应该将其作为键值对列表发送。
{
"key": "value",
"file": open("/path/to/file", "rb"),
}
回答你的问题...
is it possible to do it?
使用同一个密钥似乎无法上传多个文件(在测试中),但可以将它们分散到多个密钥上以实现相同的目的目标。或者,您可以将视图设置为仅处理单个文件,并进行涵盖不同测试用例的多个测试(apartments.csv
、accounts.csv
等)。
您的异常被触发是因为您传递的是单个列表而不是字典,而 Django 无法正确解析它们。
你 可能会运气好 直接形成请求字典 using a QueryDict
这是 Django 使用的表单数据的内部表示。
data = QueryDict(mutable=True)
data.setlist("files", [
open('accounts/importer/accounts.csv', 'rb'),
open('accounts/importer/apartments.csv', 'rb')
])
因为这更接近于通过浏览器发送的数据。这尚未经过测试,但这是在一个键中发送多个非文件值的方法。
我正在尝试将几个文件发送到我的后端:
class AccountsImporterTestCase(APITestCase):
def test(self):
data = [open('accounts/importer/accounts.csv'), open('accounts/importer/apartments.csv')]
response = self.client.post('/api/v1/accounts/import/', data, format='multipart')
self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED)
但是我收到一个错误:
Error
Traceback (most recent call last):
File "/vagrant/conjuntos/accounts/tests/cases.py", line 128, in test
response = self.client.post('/api/v1/accounts/import/', data, format='multipart')
File "/vagrant/venv/lib/python3.4/site-packages/rest_framework/test.py", line 168, in post
path, data=data, format=format, content_type=content_type, **extra)
File "/vagrant/venv/lib/python3.4/site-packages/rest_framework/test.py", line 89, in post
data, content_type = self._encode_data(data, format, content_type)
File "/vagrant/venv/lib/python3.4/site-packages/rest_framework/test.py", line 64, in _encode_data
ret = renderer.render(data)
File "/vagrant/venv/lib/python3.4/site-packages/rest_framework/renderers.py", line 757, in render
return encode_multipart(self.BOUNDARY, data)
File "/vagrant/venv/lib/python3.4/site-packages/django/test/client.py", line 156, in encode_multipart
for (key, value) in data.items():
AttributeError: 'list' object has no attribute 'items'
我知道我没有正确准备数据,但可以这样做吗?如何做?。谢谢!
更新: 尝试@Kevin Brown 解决方案
def test(self):
data = QueryDict('', mutable=True)
data.setlist('files', [open('accounts/importer/accounts.csv'), open('accounts/importer/apartments.csv')])
response = self.client.post('/api/v1/accounts/import/', data, format='multipart')
self.assertEqual(response.status_code, status.HTTP_202_ACCEPTED)
得到以下内容:
Error
Traceback (most recent call last):
File "/vagrant/conjuntos/accounts/tests/cases.py", line 130, in test
response = self.client.post('/api/v1/accounts/import/', data, format='multipart')
File "/vagrant/venv/lib/python3.4/site-packages/rest_framework/test.py", line 168, in post
path, data=data, format=format, content_type=content_type, **extra)
File "/vagrant/venv/lib/python3.4/site-packages/rest_framework/test.py", line 89, in post
data, content_type = self._encode_data(data, format, content_type)
File "/vagrant/venv/lib/python3.4/site-packages/rest_framework/test.py", line 64, in _encode_data
ret = renderer.render(data)
File "/vagrant/venv/lib/python3.4/site-packages/rest_framework/renderers.py", line 757, in render
return encode_multipart(self.BOUNDARY, data)
File "/vagrant/venv/lib/python3.4/site-packages/django/test/client.py", line 182, in encode_multipart
return b'\r\n'.join(lines)
TypeError: sequence item 4: expected bytes, bytearray, or an object with the buffer interface, str found
检查这是否解决了您的问题,因为从错误中可以清楚地看出数据不应该是 list
data = {"account_csv": open('accounts/importer/accounts.csv'), "apartments_csv": open('accounts/importer/apartments.csv')}
这个 link 你可能会觉得有用 Uploading multiple files in a single request using python requests module
您正在向视图发送文件列表,但发送不正确。当您将数据发送到视图时,无论是 Django 视图还是 DRF 视图,您都应该将其作为键值对列表发送。
{
"key": "value",
"file": open("/path/to/file", "rb"),
}
回答你的问题...
is it possible to do it?
使用同一个密钥似乎无法上传多个文件(在测试中),但可以将它们分散到多个密钥上以实现相同的目的目标。或者,您可以将视图设置为仅处理单个文件,并进行涵盖不同测试用例的多个测试(apartments.csv
、accounts.csv
等)。
您的异常被触发是因为您传递的是单个列表而不是字典,而 Django 无法正确解析它们。
你 可能会运气好 直接形成请求字典 using a QueryDict
这是 Django 使用的表单数据的内部表示。
data = QueryDict(mutable=True)
data.setlist("files", [
open('accounts/importer/accounts.csv', 'rb'),
open('accounts/importer/apartments.csv', 'rb')
])
因为这更接近于通过浏览器发送的数据。这尚未经过测试,但这是在一个键中发送多个非文件值的方法。