Browse Source

dcim: added json flat renderer.

Zach Moody 9 years ago
parent
commit
8f5543fe88
3 changed files with 73 additions and 3 deletions
  1. 2 2
      netbox/dcim/api/views.py
  2. 50 0
      netbox/dcim/tests/test_apis.py
  3. 21 1
      netbox/extras/api/renderers.py

+ 2 - 2
netbox/dcim/api/views.py

@@ -16,7 +16,7 @@ from .serializers import SiteSerializer, RackGroupSerializer, RackSerializer, Ra
     ManufacturerSerializer, DeviceTypeSerializer, DeviceRoleSerializer, PlatformSerializer, DeviceSerializer, \
     DeviceNestedSerializer, ConsolePortSerializer, ConsoleServerPortSerializer, PowerPortSerializer, \
     PowerOutletSerializer, InterfaceSerializer, InterfaceDetailSerializer, InterfaceConnectionSerializer
-from extras.api.renderers import BINDZoneRenderer
+from extras.api.renderers import BINDZoneRenderer, FlatJSONRenderer
 from utilities.api import ServiceUnavailable
 
 
@@ -198,7 +198,7 @@ class DeviceListView(generics.ListAPIView):
         .prefetch_related('primary_ip__nat_outside')
     serializer_class = DeviceSerializer
     filter_class = DeviceFilter
-    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES + [BINDZoneRenderer]
+    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES + [BINDZoneRenderer, FlatJSONRenderer]
 
 
 class DeviceDetailView(generics.RetrieveAPIView):

+ 50 - 0
netbox/dcim/tests/test_apis.py

@@ -322,6 +322,14 @@ class DeviceTest(APITestCase):
 
     nested_fields = ['id', 'name']
 
+    # Holds primary IP nested fields until api tests
+    # can be made and fields imported.
+    primary_ip = [
+        'id',
+        'family',
+        'address'
+    ]
+
     def test_get_list(self, endpoint='/api/dcim/devices/'):
         response = self.client.get(endpoint)
         content = json.loads(response.content)
@@ -349,6 +357,48 @@ class DeviceTest(APITestCase):
                 sorted(RackTest.nested_fields),
             )
 
+    def test_get_list_flat(self, endpoint='/api/dcim/devices/?format=json_flat'):
+
+        flat_fields = [
+            'comments',
+            'device_role_id',
+            'device_role_name',
+            'device_role_slug',
+            'device_type_id',
+            'device_type_manufacturer_id',
+            'device_type_manufacturer_name',
+            'device_type_manufacturer_slug',
+            'device_type_model',
+            'device_type_slug',
+            'display_name',
+            'face',
+            'id',
+            'name',
+            'platform_id',
+            'platform_name',
+            'platform_slug',
+            'position',
+            'primary_ip_address',
+            'primary_ip_family',
+            'primary_ip_id',
+            'rack_display_name',
+            'rack_facility_id',
+            'rack_id',
+            'rack_name',
+            'ro_snmp',
+            'serial',
+            'status',
+        ]
+
+        response = self.client.get(endpoint)
+        content = json.loads(response.content)
+        self.assertEqual(response.status_code, status.HTTP_200_OK)
+        device = content[0]
+        self.assertEqual(
+            sorted(device.keys()),
+            sorted(flat_fields),
+        )
+
     def test_get_detail(self, endpoint='/api/dcim/devices/1/'):
         response = self.client.get(endpoint)
         content = json.loads(response.content)

+ 21 - 1
netbox/extras/api/renderers.py

@@ -1,6 +1,6 @@
+import json
 from rest_framework import renderers
 
-
 # IP address family designations
 AF = {
     4: 'A',
@@ -29,3 +29,23 @@ class BINDZoneRenderer(renderers.BaseRenderer):
                 except KeyError:
                     pass
         return '\n'.join(records)
+
+
+class FlatJSONRenderer(renderers.BaseRenderer):
+    """
+    Flattens a nested JSON reponse.
+    """
+    format = 'json_flat'
+    media_type = 'application/json'
+
+    def render(self, data, media_type=None, renderer_context=None):
+
+        def flatten(entry):
+            for key, val in entry.iteritems():
+                if isinstance(val, dict):
+                    for child_key, child_val in flatten(val):
+                        yield "{}_{}".format(key, child_key), child_val
+                else:
+                    yield key, val
+
+        return json.dumps([dict(flatten(i)) for i in data])