Я работал над проектом, в котором я мог бы добавить CSV для загрузки сведений о рубашках в базу данных.
Я написал набор, который принимает входные данные CSV-файлов рубашки из request.data в django rest framework, и янаписание теста для того же.Хотя во время написания тестового примера вместо создания отдельного файла CSV я создал CSV из фрейма данных pandas внутри тестового примера и преобразовал его в TextIOWrapper для передачи в качестве данных запроса.Это приводит к следующей ошибке:
File "/Users/prasoon/projects/shirt_details/post_shirt_csv/tests/test_post_shirt_dataset.py", line 175, in test_shirt_dataset_post
response = self.api_client.post(reverse('post-shirt-csv-dataset', kwargs={'session_id': self.session.id}), {'csv_files': [fp1, fp2]})
File "/Users/prasoon/projects/venv/lib/python3.6/site-packages/rest_framework/test.py", line 300, in post
path, data=data, format=format, content_type=content_type, **extra)
File "/Users/prasoon/projects/venv/lib/python3.6/site-packages/rest_framework/test.py", line 212, in post
data, content_type = self._encode_data(data, format, content_type)
File "/Users/prasoon/projects/venv/lib/python3.6/site-packages/rest_framework/test.py", line 184, in _encode_data
ret = renderer.render(data)
File "/Users/prasoon/projects/venv/lib/python3.6/site-packages/rest_framework/renderers.py", line 920, in render
return encode_multipart(self.BOUNDARY, data)
File "/Users/prasoon/projects/venv/lib/python3.6/site-packages/django/test/client.py", line 198, in encode_multipart
lines.extend(encode_file(boundary, key, item))
File "/Users/prasoon/projects/venv/lib/python3.6/site-packages/django/test/client.py", line 247, in encode_file
to_bytes(file.read())
File "/Users/prasoon/projects/venv/bin/../lib/python3.6/codecs.py", line 320, in decode
data = self.buffer + input
TypeError: can't concat str to bytes
Эта вещь работает, когда я открываю файл и передаю его вместо создания строки.Ниже будет более ясно:
Файл тестов:
class TestPostNewDataset(TestCase):
@classmethod
def setUpTestData(cls):
cls.user = CurrentUserFactory()
cls.test_data1 = {"no":[1,2,3],"colour":["Red","Blue","Gray"],"Size":["XL","L","M"],"Brand":["Nike","Polo","Adidas"],"Price":[800,600,1000]}
cls.test_data2 = {"no":[1,2,3],"colour":["Black","Blue","Red"],"Size":["S","M","L"],"Brand":["Nike","Levis","Nike"],"Price":[2000,900,1000]}
cls.test_df1 = pd.DataFrame(cls.test_data1)
cls.test_df2 = pd.DataFrame(cls.test_data2)
cls.session = CurrentSessionFactory(user=cls.user)
def test_shirt_dataset_post(self):
"Test request to post shirt dataset"
fp1 = TextIOWrapper(StringIO(self.test_df1))
fp2 = TextIOWrapper(StringIO(self.test_df2))
response = self.api_client.post(reverse("post-shirt-csv-dataset", kwargs={'session_id':self.session.id}),{'csv_files':[fp1,fp2]})
self.assertEqual(response.status_code,status.HTTP_200_OK)
Соответствующий файл представлений:
class CsvReadViewset(viewsets.ModelViewSet):
authentication_classes = (BasicAuthentication,)
permission_classes = (IsAuthenticated,)
serializer_class = ShirtSerializer
queryset = Shirt.objects.all()
def addShirt(self,request,*args,**kwargs):
csvs = request.data["csv_files"]
current_session = CurrentSession.objects.get(session_id=kwargs["session_id"])
for shirt_csv in csvs:
shirt_df = pd.read_csv(shirt_csv)
for index,row in short_df.iterrows():
s = Shirt(colour=row["colour"],
brand=row["Brand"],
size=row["Size"],
price=row["Price"],
created_in=current_session)
s.save()
return Response(status=status.HTTP_200_OK)
Интересно то, что при тестированииcase принимает отдельный файл в качестве входных данных, он работает нормально.То есть, если я заменю test_shirt_dataset_post следующим:
def test_shirt_dataset_post(self):
with open(os.path.join(os.path.abspath(__file__ + "/../"), 'shirtcsv1.csv')) as fp1, open(os.path.join(os.path.abspath(__file__ + "/../"), 'shirtcsv2.csv')) as fp2:
response = self.api_client.post(reverse("post-shirt-csv-dataset",kwargs={'session_id':self.session.id}),{'csv_files':[fp1,fp2]})
self.assertEqual(response.status_code,status.HTTP_200_OK)
Ожидаемый результат - это тестовый пример для работы.Но здесь выдает ошибку, как показано.Причина добавления TextIOWrapper заключается в том, что тип fp в with open(....) as fp
- это _io.TextIOWrapper.Хотя, тогда он выдает эту ошибку.Любая помощь будет оценена.