Django REST Framework: ошибка при тестировании POST-запроса со списком - PullRequest
2 голосов
/ 06 октября 2019

У меня есть тестовое представление:

@api_view(['POST'])
@permission_classes([AllowAny])
@authentication_classes([])
def test_view(request):
    return Response(request.data)

Оно зарегистрировано в urls.py:

urlpatterns = [
    path('api/test/', test_view)
]

Когда я пытаюсь POST [{"a": 1}, {"a": 2}] вручную через пользовательский интерфейс REST Frameworks,все работает нормально.

Однако, если я напишу тест для него, произойдет неожиданная ошибка. Вот тест

from rest_framework.test import APITestCase

class ViewTest(APITestCase):
    def test_it(self):
        response = self.client.post('/api/test/', [{"a": 1}, {"a": 2}])
        print(response)

, который выдает следующую ошибку:

Traceback (most recent call last):
  File "C:\development\HeedView\backend\clients\api\tests.py", line 13, in test_it
    response = self.client.post('/api/test/', [{"a":1}, {"a": 2}])
  File "C:\development\HeedView\venv\lib\site-packages\rest_framework\test.py", line 300, in post
    path, data=data, format=format, content_type=content_type, **extra)
  File "C:\development\HeedView\venv\lib\site-packages\rest_framework\test.py", line 212, in post
    data, content_type = self._encode_data(data, format, content_type)
  File "C:\development\HeedView\venv\lib\site-packages\rest_framework\test.py", line 184, in _encode_data
    ret = renderer.render(data)
  File "C:\development\HeedView\venv\lib\site-packages\rest_framework\renderers.py", line 921, in render
    return encode_multipart(self.BOUNDARY, data)
  File "C:\development\HeedView\venv\lib\site-packages\django\test\client.py", line 194, in encode_multipart
    for (key, value) in data.items():
AttributeError: 'list' object has no attribute 'items'

Как объяснить это поведение?

Ответы [ 2 ]

1 голос
/ 07 октября 2019

Чтобы передать данные JSON, вам нужно добавить format='json'. Этот тест работает:

from rest_framework.test import APITestCase

class ViewTest(APITestCase):
    def test_it(self):
        response = self.client.post('/api/test/', [{"a": "1"}, {"a": 2}], format='json')
        print(response.json())

Кроме того, ваш оригинальный тест работает, если вы установите формат по умолчанию в settings.py:

REST_FRAMEWORK = {
    ...
    'TEST_REQUEST_DEFAULT_FORMAT': 'json'
}

Еслиформат не указан:

APIClient Rest Framework расширяет существующий класс клиента Django. Документация для Client.post объясняет, что:

Пары ключ-значение в словаре данных используются для передачи данных POST. Например:

... client.post('/login/', {'name': 'fred', 'passwd': 'secret'})

... [проверяет] эти данные POST:

name=fred&passwd=secret

Вашоригинальный тест возвращает ошибку, потому что если формат не указан, то Django ожидает словарь, а не список.

1 голос
/ 06 октября 2019

Вот тест, который будет работать:

from rest_framework.test import APITestCase

class ViewTest(APITestCase):
    def test_it(self):
        response = self.client.post('/api/test/', json.dumps([{"a": "1"}, {"a": 2}]),
                                    content_type='application/json')
        print(response.json())

Однако я до сих пор не понимаю, почему я должен использовать json.dumps (т.е. дать данные в виде строки) и явно указать тип содержимого,Этого никогда не случалось с данными запроса типа dict.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...