Просмотр исходного кода

Map QueryDict to dict inside get_non_list_response()

Jeremy Stretch 1 неделя назад
Родитель
Сommit
42df031c06
2 измененных файлов с 16 добавлено и 7 удалено
  1. 12 0
      netbox/dcim/tests/test_api.py
  2. 4 7
      netbox/netbox/api/viewsets/mixins.py

+ 12 - 0
netbox/dcim/tests/test_api.py

@@ -493,6 +493,18 @@ class SiteTestCase(APIViewTestCases.APIViewTestCase):
         # A non-list body is described by its type, so that the client can see what was sent
         self.assertEqual(response.data['detail'], 'Expected a list of objects, but got dict.')
 
+        # A multipart body reaches the bulk action as a QueryDict, which must be reported as the
+        # dict the client submitted rather than by that internal class name
+        response = self.client.patch(
+            self._get_list_url(), {'id': site.pk, 'description': 'x'}, format='multipart', **self.header
+        )
+
+        self.assertHttpStatus(response, status.HTTP_400_BAD_REQUEST)
+        self.assertEqual(response.data['detail'], 'Expected a list of objects, but got dict.')
+
+        site.refresh_from_db()
+        self.assertEqual(site.description, '')
+
     def test_bulk_write_objects_empty_body(self):
         """
         Address a list endpoint with no body at all. An absent body reaches the bulk actions as an

+ 4 - 7
netbox/netbox/api/viewsets/mixins.py

@@ -93,16 +93,13 @@ def get_non_list_response(data):
     if isinstance(data, list):
         return None
 
-    # A request with no body at all arrives here as an empty dict, so reporting its type would tell
-    # the client only that it "got dict" -- unhelpful for what is the likeliest way to reach this
-    # point: a DELETE addressed to a list endpoint with nothing in the body. An explicitly submitted
-    # empty object is indistinguishable at this stage, and wants the same message anyway.
     if data is None or data == {} or data == '':
         detail = _('Expected a list of objects, but no data was submitted.')
     else:
-        detail = _('Expected a list of objects, but got {datatype}.').format(
-            datatype=type(data).__name__
-        )
+        # A multipart body arrives as a QueryDict rather than as a plain dict, so report any mapping
+        # by the type the client submitted rather than by the class which happens to carry it.
+        datatype = 'dict' if isinstance(data, dict) else type(data).__name__
+        detail = _('Expected a list of objects, but got {datatype}.').format(datatype=datatype)
 
     return Response({'detail': detail}, status=status.HTTP_400_BAD_REQUEST)