Browse Source

Converted nested serializers to HyperlinkedModelSerializer

Jeremy Stretch 8 years ago
parent
commit
fa900d5dbb

+ 32 - 23
netbox/circuits/api/serializers.py

@@ -1,9 +1,9 @@
 from rest_framework import serializers
 
 from circuits.models import Provider, Circuit, CircuitTermination, CircuitType
-from dcim.api.serializers import SiteNestedSerializer, NestedInterfaceSerializer
+from dcim.api.serializers import NestedSiteSerializer, ChildInterfaceSerializer
 from extras.api.serializers import CustomFieldSerializer
-from tenancy.api.serializers import TenantNestedSerializer
+from tenancy.api.serializers import NestedTenantSerializer
 
 
 #
@@ -14,14 +14,17 @@ class ProviderSerializer(CustomFieldSerializer, serializers.ModelSerializer):
 
     class Meta:
         model = Provider
-        fields = ['id', 'name', 'slug', 'asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', 'comments',
-                  'custom_fields']
+        fields = [
+            'id', 'name', 'slug', 'asn', 'account', 'portal_url', 'noc_contact', 'admin_contact', 'comments',
+            'custom_fields',
+        ]
 
 
-class ProviderNestedSerializer(ProviderSerializer):
+class NestedProviderSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(ProviderSerializer.Meta):
-        fields = ['id', 'name', 'slug']
+    class Meta:
+        model = Provider
+        fields = ['id', 'url', 'name', 'slug']
 
 
 #
@@ -35,10 +38,11 @@ class CircuitTypeSerializer(serializers.ModelSerializer):
         fields = ['id', 'name', 'slug']
 
 
-class CircuitTypeNestedSerializer(CircuitTypeSerializer):
+class NestedCircuitTypeSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(CircuitTypeSerializer.Meta):
-        pass
+    class Meta:
+        model = CircuitType
+        fields = ['id', 'url', 'name', 'slug']
 
 
 #
@@ -46,8 +50,8 @@ class CircuitTypeNestedSerializer(CircuitTypeSerializer):
 #
 
 class CircuitTerminationSerializer(serializers.ModelSerializer):
-    site = SiteNestedSerializer()
-    interface = NestedInterfaceSerializer()
+    site = NestedSiteSerializer()
+    interface = ChildInterfaceSerializer()
 
     class Meta:
         model = CircuitTermination
@@ -58,27 +62,32 @@ class CircuitTerminationSerializer(serializers.ModelSerializer):
 # Circuits
 #
 
-
 class CircuitSerializer(CustomFieldSerializer, serializers.ModelSerializer):
-    provider = ProviderNestedSerializer()
-    type = CircuitTypeNestedSerializer()
-    tenant = TenantNestedSerializer()
+    provider = NestedProviderSerializer()
+    type = NestedCircuitTypeSerializer()
+    tenant = NestedTenantSerializer()
 
     class Meta:
         model = Circuit
-        fields = ['id', 'cid', 'provider', 'type', 'tenant', 'install_date', 'commit_rate', 'description', 'comments',
-                  'custom_fields']
+        fields = [
+            'id', 'cid', 'provider', 'type', 'tenant', 'install_date', 'commit_rate', 'description', 'comments',
+            'custom_fields',
+        ]
 
 
-class CircuitNestedSerializer(CircuitSerializer):
+class NestedCircuitSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(CircuitSerializer.Meta):
-        fields = ['id', 'cid']
+    class Meta:
+        model = Circuit
+        fields = ['id', 'url', 'cid']
 
 
+# TODO: Delete this
 class CircuitDetailSerializer(CircuitSerializer):
     terminations = CircuitTerminationSerializer(many=True)
 
     class Meta(CircuitSerializer.Meta):
-        fields = ['id', 'cid', 'provider', 'type', 'tenant', 'install_date', 'commit_rate', 'description', 'comments',
-                  'terminations', 'custom_fields']
+        fields = [
+            'id', 'cid', 'provider', 'type', 'tenant', 'install_date', 'commit_rate', 'description', 'comments',
+            'terminations', 'custom_fields',
+        ]

+ 118 - 90
netbox/dcim/api/serializers.py

@@ -8,7 +8,7 @@ from dcim.models import (
     SUBDEVICE_ROLE_CHILD, SUBDEVICE_ROLE_PARENT,
 )
 from extras.api.serializers import CustomFieldSerializer
-from tenancy.api.serializers import TenantNestedSerializer
+from tenancy.api.serializers import NestedTenantSerializer
 
 
 #
@@ -16,19 +16,22 @@ from tenancy.api.serializers import TenantNestedSerializer
 #
 
 class SiteSerializer(CustomFieldSerializer, serializers.ModelSerializer):
-    tenant = TenantNestedSerializer()
+    tenant = NestedTenantSerializer()
 
     class Meta:
         model = Site
-        fields = ['id', 'name', 'slug', 'tenant', 'facility', 'asn', 'physical_address', 'shipping_address',
-                  'contact_name', 'contact_phone', 'contact_email', 'comments', 'custom_fields', 'count_prefixes',
-                  'count_vlans', 'count_racks', 'count_devices', 'count_circuits']
+        fields = [
+            'id', 'name', 'slug', 'tenant', 'facility', 'asn', 'physical_address', 'shipping_address', 'contact_name',
+            'contact_phone', 'contact_email', 'comments', 'custom_fields', 'count_prefixes', 'count_vlans',
+            'count_racks', 'count_devices', 'count_circuits',
+        ]
 
 
-class SiteNestedSerializer(SiteSerializer):
+class NestedSiteSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(SiteSerializer.Meta):
-        fields = ['id', 'name', 'slug']
+    class Meta:
+        model = Site
+        fields = ['id', 'url', 'name', 'slug']
 
 
 #
@@ -36,17 +39,18 @@ class SiteNestedSerializer(SiteSerializer):
 #
 
 class RackGroupSerializer(serializers.ModelSerializer):
-    site = SiteNestedSerializer()
+    site = NestedSiteSerializer()
 
     class Meta:
         model = RackGroup
         fields = ['id', 'name', 'slug', 'site']
 
 
-class RackGroupNestedSerializer(RackGroupSerializer):
+class NestedRackGroupSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(SiteSerializer.Meta):
-        fields = ['id', 'name', 'slug']
+    class Meta:
+        model = RackGroup
+        fields = ['id', 'url', 'name', 'slug']
 
 
 #
@@ -60,10 +64,11 @@ class RackRoleSerializer(serializers.ModelSerializer):
         fields = ['id', 'name', 'slug', 'color']
 
 
-class RackRoleNestedSerializer(RackRoleSerializer):
+class NestedRackRoleSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(RackRoleSerializer.Meta):
-        fields = ['id', 'name', 'slug']
+    class Meta:
+        model = RackRole
+        fields = ['id', 'url', 'name', 'slug']
 
 
 #
@@ -72,21 +77,24 @@ class RackRoleNestedSerializer(RackRoleSerializer):
 
 
 class RackSerializer(CustomFieldSerializer, serializers.ModelSerializer):
-    site = SiteNestedSerializer()
-    group = RackGroupNestedSerializer()
-    tenant = TenantNestedSerializer()
-    role = RackRoleNestedSerializer()
+    site = NestedSiteSerializer()
+    group = NestedRackGroupSerializer()
+    tenant = NestedTenantSerializer()
+    role = NestedRackRoleSerializer()
 
     class Meta:
         model = Rack
-        fields = ['id', 'name', 'facility_id', 'display_name', 'site', 'group', 'tenant', 'role', 'type', 'width',
-                  'u_height', 'desc_units', 'comments', 'custom_fields']
+        fields = [
+            'id', 'name', 'facility_id', 'display_name', 'site', 'group', 'tenant', 'role', 'type', 'width', 'u_height',
+            'desc_units', 'comments', 'custom_fields',
+        ]
 
 
-class RackNestedSerializer(RackSerializer):
+class NestedRackSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(RackSerializer.Meta):
-        fields = ['id', 'name', 'facility_id', 'display_name']
+    class Meta:
+        model = Rack
+        fields = ['id', 'url', 'name', 'display_name']
 
 
 class RackDetailSerializer(RackSerializer):
@@ -94,19 +102,21 @@ class RackDetailSerializer(RackSerializer):
     rear_units = serializers.SerializerMethodField()
 
     class Meta(RackSerializer.Meta):
-        fields = ['id', 'name', 'facility_id', 'display_name', 'site', 'group', 'tenant', 'role', 'type', 'width',
-                  'u_height', 'desc_units', 'comments', 'custom_fields', 'front_units', 'rear_units']
+        fields = [
+            'id', 'name', 'facility_id', 'display_name', 'site', 'group', 'tenant', 'role', 'type', 'width', 'u_height',
+            'desc_units', 'comments', 'custom_fields', 'front_units', 'rear_units',
+        ]
 
     def get_front_units(self, obj):
         units = obj.get_rack_units(face=RACK_FACE_FRONT)
         for u in units:
-            u['device'] = DeviceNestedSerializer(u['device']).data if u['device'] else None
+            u['device'] = NestedDeviceSerializer(u['device']).data if u['device'] else None
         return units
 
     def get_rear_units(self, obj):
         units = obj.get_rack_units(face=RACK_FACE_REAR)
         for u in units:
-            u['device'] = DeviceNestedSerializer(u['device']).data if u['device'] else None
+            u['device'] = NestedDeviceSerializer(u['device']).data if u['device'] else None
         return units
 
 
@@ -121,10 +131,11 @@ class ManufacturerSerializer(serializers.ModelSerializer):
         fields = ['id', 'name', 'slug']
 
 
-class ManufacturerNestedSerializer(ManufacturerSerializer):
+class NestedManufacturerSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(ManufacturerSerializer.Meta):
-        pass
+    class Meta:
+        model = Manufacturer
+        fields = ['id', 'url', 'name', 'slug']
 
 
 #
@@ -132,15 +143,17 @@ class ManufacturerNestedSerializer(ManufacturerSerializer):
 #
 
 class DeviceTypeSerializer(CustomFieldSerializer, serializers.ModelSerializer):
-    manufacturer = ManufacturerNestedSerializer()
+    manufacturer = NestedManufacturerSerializer()
     subdevice_role = serializers.SerializerMethodField()
     instance_count = serializers.IntegerField(source='instances.count', read_only=True)
 
     class Meta:
         model = DeviceType
-        fields = ['id', 'manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth',
-                  'interface_ordering', 'is_console_server', 'is_pdu', 'is_network_device', 'subdevice_role',
-                  'comments', 'custom_fields', 'instance_count']
+        fields = [
+            'id', 'manufacturer', 'model', 'slug', 'part_number', 'u_height', 'is_full_depth', 'interface_ordering',
+            'is_console_server', 'is_pdu', 'is_network_device', 'subdevice_role', 'comments', 'custom_fields',
+            'instance_count',
+        ]
 
     def get_subdevice_role(self, obj):
         return {
@@ -150,47 +163,55 @@ class DeviceTypeSerializer(CustomFieldSerializer, serializers.ModelSerializer):
         }[obj.subdevice_role]
 
 
-class DeviceTypeNestedSerializer(DeviceTypeSerializer):
+class NestedDeviceTypeSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(DeviceTypeSerializer.Meta):
-        fields = ['id', 'manufacturer', 'model', 'slug']
+    class Meta:
+        model = DeviceType
+        fields = ['id', 'url', 'manufacturer', 'model', 'slug']
 
 
-class ConsolePortTemplateNestedSerializer(serializers.ModelSerializer):
+class ConsolePortTemplateSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = ConsolePortTemplate
         fields = ['id', 'name']
 
 
-class ConsoleServerPortTemplateNestedSerializer(serializers.ModelSerializer):
+class ConsoleServerPortTemplateSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = ConsoleServerPortTemplate
         fields = ['id', 'name']
 
 
-class PowerPortTemplateNestedSerializer(serializers.ModelSerializer):
+class PowerPortTemplateSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = PowerPortTemplate
         fields = ['id', 'name']
 
 
-class PowerOutletTemplateNestedSerializer(serializers.ModelSerializer):
+class PowerOutletTemplateSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = PowerOutletTemplate
         fields = ['id', 'name']
 
 
-class InterfaceTemplateNestedSerializer(serializers.ModelSerializer):
+class InterfaceTemplateSerializer(serializers.ModelSerializer):
 
     class Meta:
         model = InterfaceTemplate
         fields = ['id', 'name', 'form_factor', 'mgmt_only']
 
 
+class DeviceBayTemplateSerializer(serializers.ModelSerializer):
+
+    class Meta:
+        model = DeviceBay
+        fields = ['id', 'name',]
+
+
 #
 # Device roles
 #
@@ -202,10 +223,11 @@ class DeviceRoleSerializer(serializers.ModelSerializer):
         fields = ['id', 'name', 'slug', 'color']
 
 
-class DeviceRoleNestedSerializer(DeviceRoleSerializer):
+class NestedDeviceRoleSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(DeviceRoleSerializer.Meta):
-        fields = ['id', 'name', 'slug']
+    class Meta:
+        model = DeviceRole
+        fields = ['id', 'url', 'name', 'slug']
 
 
 #
@@ -219,40 +241,43 @@ class PlatformSerializer(serializers.ModelSerializer):
         fields = ['id', 'name', 'slug', 'rpc_client']
 
 
-class PlatformNestedSerializer(PlatformSerializer):
+class NestedPlatformSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(PlatformSerializer.Meta):
-        fields = ['id', 'name', 'slug']
+    class Meta:
+        model = Platform
+        fields = ['id', 'url', 'name', 'slug']
 
 
 #
 # Devices
 #
 
-# Cannot import ipam.api.IPAddressNestedSerializer due to circular dependency
-class DeviceIPAddressNestedSerializer(serializers.ModelSerializer):
+# Cannot import ipam.api.NestedIPAddressSerializer due to circular dependency
+class DeviceIPAddressSerializer(serializers.HyperlinkedModelSerializer):
 
     class Meta:
         model = IPAddress
-        fields = ['id', 'family', 'address']
+        fields = ['id', 'url', 'family', 'address']
 
 
 class DeviceSerializer(CustomFieldSerializer, serializers.ModelSerializer):
-    device_type = DeviceTypeNestedSerializer()
-    device_role = DeviceRoleNestedSerializer()
-    tenant = TenantNestedSerializer()
-    platform = PlatformNestedSerializer()
-    rack = RackNestedSerializer()
-    primary_ip = DeviceIPAddressNestedSerializer()
-    primary_ip4 = DeviceIPAddressNestedSerializer()
-    primary_ip6 = DeviceIPAddressNestedSerializer()
+    device_type = NestedDeviceTypeSerializer()
+    device_role = NestedDeviceRoleSerializer()
+    tenant = NestedTenantSerializer()
+    platform = NestedPlatformSerializer()
+    rack = NestedRackSerializer()
+    primary_ip = DeviceIPAddressSerializer()
+    primary_ip4 = DeviceIPAddressSerializer()
+    primary_ip6 = DeviceIPAddressSerializer()
     parent_device = serializers.SerializerMethodField()
 
     class Meta:
         model = Device
-        fields = ['id', 'name', 'display_name', 'device_type', 'device_role', 'tenant', 'platform', 'serial',
-                  'asset_tag', 'rack', 'position', 'face', 'parent_device', 'status', 'primary_ip', 'primary_ip4',
-                  'primary_ip6', 'comments', 'custom_fields']
+        fields = [
+            'id', 'name', 'display_name', 'device_type', 'device_role', 'tenant', 'platform', 'serial',  'asset_tag',
+            'rack', 'position', 'face', 'parent_device', 'status', 'primary_ip', 'primary_ip4', 'primary_ip6',
+            'comments', 'custom_fields',
+        ]
 
     def get_parent_device(self, obj):
         try:
@@ -269,11 +294,11 @@ class DeviceSerializer(CustomFieldSerializer, serializers.ModelSerializer):
         }
 
 
-class DeviceNestedSerializer(serializers.ModelSerializer):
+class NestedDeviceSerializer(serializers.HyperlinkedModelSerializer):
 
     class Meta:
         model = Device
-        fields = ['id', 'name', 'display_name']
+        fields = ['id', 'url', 'name', 'display_name']
 
 
 #
@@ -281,18 +306,18 @@ class DeviceNestedSerializer(serializers.ModelSerializer):
 #
 
 class ConsoleServerPortSerializer(serializers.ModelSerializer):
-    device = DeviceNestedSerializer()
+    device = NestedDeviceSerializer()
 
     class Meta:
         model = ConsoleServerPort
         fields = ['id', 'device', 'name', 'connected_console']
 
 
-class NestedConsoleServerPortSerializer(ConsoleServerPortSerializer):
+class ChildConsoleServerPortSerializer(serializers.HyperlinkedModelSerializer):
 
     class Meta:
         model = ConsoleServerPort
-        fields = ['id', 'name', 'connected_console']
+        fields = ['id', 'url', 'name', 'connected_console']
 
 
 #
@@ -300,7 +325,7 @@ class NestedConsoleServerPortSerializer(ConsoleServerPortSerializer):
 #
 
 class ConsolePortSerializer(serializers.ModelSerializer):
-    device = DeviceNestedSerializer()
+    device = NestedDeviceSerializer()
     cs_port = ConsoleServerPortSerializer()
 
     class Meta:
@@ -308,11 +333,11 @@ class ConsolePortSerializer(serializers.ModelSerializer):
         fields = ['id', 'device', 'name', 'cs_port', 'connection_status']
 
 
-class NestedConsolePortSerializer(ConsolePortSerializer):
+class ChildConsolePortSerializer(serializers.HyperlinkedModelSerializer):
 
     class Meta:
         model = ConsolePort
-        fields = ['id', 'name', 'cs_port', 'connection_status']
+        fields = ['id', 'url', 'name', 'cs_port', 'connection_status']
 
 
 #
@@ -320,18 +345,18 @@ class NestedConsolePortSerializer(ConsolePortSerializer):
 #
 
 class PowerOutletSerializer(serializers.ModelSerializer):
-    device = DeviceNestedSerializer()
+    device = NestedDeviceSerializer()
 
     class Meta:
         model = PowerOutlet
         fields = ['id', 'device', 'name', 'connected_port']
 
 
-class NestedPowerOutletSerializer(PowerOutletSerializer):
+class ChildPowerOutletSerializer(serializers.HyperlinkedModelSerializer):
 
     class Meta:
         model = PowerOutlet
-        fields = ['id', 'name', 'connected_port']
+        fields = ['id', 'url', 'name', 'connected_port']
 
 
 #
@@ -339,7 +364,7 @@ class NestedPowerOutletSerializer(PowerOutletSerializer):
 #
 
 class PowerPortSerializer(serializers.ModelSerializer):
-    device = DeviceNestedSerializer()
+    device = NestedDeviceSerializer()
     power_outlet = PowerOutletSerializer()
 
     class Meta:
@@ -347,11 +372,11 @@ class PowerPortSerializer(serializers.ModelSerializer):
         fields = ['id', 'device', 'name', 'power_outlet', 'connection_status']
 
 
-class NestedPowerPortSerializer(PowerPortSerializer):
+class ChildPowerPortSerializer(serializers.HyperlinkedModelSerializer):
 
     class Meta:
         model = PowerPort
-        fields = ['id', 'name', 'power_outlet', 'connection_status']
+        fields = ['id', 'url', 'name', 'power_outlet', 'connection_status']
 
 
 #
@@ -359,7 +384,7 @@ class NestedPowerPortSerializer(PowerPortSerializer):
 #
 
 class InterfaceSerializer(serializers.ModelSerializer):
-    device = DeviceNestedSerializer()
+    device = NestedDeviceSerializer()
     form_factor = serializers.ReadOnlyField(source='get_form_factor_display')
 
     class Meta:
@@ -367,18 +392,21 @@ class InterfaceSerializer(serializers.ModelSerializer):
         fields = ['id', 'device', 'name', 'form_factor', 'mac_address', 'mgmt_only', 'description', 'is_connected']
 
 
-class NestedInterfaceSerializer(InterfaceSerializer):
+class ChildInterfaceSerializer(serializers.HyperlinkedModelSerializer):
 
     class Meta:
         model = Interface
-        fields = ['id', 'name', 'form_factor', 'mac_address', 'mgmt_only', 'description', 'is_connected']
+        fields = ['id', 'url', 'name', 'form_factor', 'mac_address', 'mgmt_only', 'description', 'is_connected']
 
 
+# TODO: Remove this
 class InterfaceDetailSerializer(InterfaceSerializer):
 
     class Meta(InterfaceSerializer.Meta):
-        fields = ['id', 'device', 'name', 'form_factor', 'mac_address', 'mgmt_only', 'description', 'is_connected',
-                  'connected_interface']
+        fields = [
+            'id', 'device', 'name', 'form_factor', 'mac_address', 'mgmt_only', 'description', 'is_connected',
+            'connected_interface',
+        ]
 
 
 #
@@ -386,19 +414,19 @@ class InterfaceDetailSerializer(InterfaceSerializer):
 #
 
 class DeviceBaySerializer(serializers.ModelSerializer):
-    device = DeviceNestedSerializer()
-    installed_device = DeviceNestedSerializer()
+    device = NestedDeviceSerializer()
+    installed_device = NestedDeviceSerializer()
 
     class Meta:
         model = DeviceBay
         fields = ['id', 'device', 'name', 'installed_device']
 
 
-class NestedDeviceBaySerializer(DeviceBaySerializer):
+class ChildDeviceBaySerializer(serializers.HyperlinkedModelSerializer):
 
     class Meta:
         model = DeviceBay
-        fields = ['id', 'name', 'installed_device']
+        fields = ['id', 'url', 'name', 'installed_device']
 
 
 #
@@ -406,19 +434,19 @@ class NestedDeviceBaySerializer(DeviceBaySerializer):
 #
 
 class ModuleSerializer(serializers.ModelSerializer):
-    device = DeviceNestedSerializer()
-    manufacturer = ManufacturerNestedSerializer()
+    device = NestedDeviceSerializer()
+    manufacturer = NestedManufacturerSerializer()
 
     class Meta:
         model = Module
         fields = ['id', 'device', 'parent', 'name', 'manufacturer', 'part_id', 'serial', 'discovered']
 
 
-class NestedModuleSerializer(ModuleSerializer):
+class ChildModuleSerializer(serializers.HyperlinkedModelSerializer):
 
     class Meta:
         model = Module
-        fields = ['id', 'parent', 'name', 'manufacturer', 'part_id', 'serial', 'discovered']
+        fields = ['id', 'url', 'parent', 'name', 'manufacturer', 'part_id', 'serial', 'discovered']
 
 
 #

+ 14 - 14
netbox/dcim/api/urls.py

@@ -35,37 +35,37 @@ urlpatterns = [
 
     # Devices
     url(r'^devices/(?P<pk>\d+)/lldp-neighbors/$', views.LLDPNeighborsView.as_view(), name='device_lldp-neighbors'),
-    url(r'^devices/(?P<pk>\d+)/console-ports/$', views.NestedConsolePortViewSet.as_view({'get': 'list'}), name='device_consoleports'),
-    url(r'^devices/(?P<pk>\d+)/console-server-ports/$', views.NestedConsoleServerPortViewSet.as_view({'get': 'list'}), name='device_consoleserverports'),
-    url(r'^devices/(?P<pk>\d+)/power-ports/$', views.NestedPowerPortViewSet.as_view({'get': 'list'}), name='device_powerports'),
-    url(r'^devices/(?P<pk>\d+)/power-outlets/$', views.NestedPowerOutletViewSet.as_view({'get': 'list'}), name='device_poweroutlets'),
-    url(r'^devices/(?P<pk>\d+)/interfaces/$', views.NestedInterfaceViewSet.as_view({'get': 'list'}), name='device_interfaces'),
-    url(r'^devices/(?P<pk>\d+)/device-bays/$', views.NestedDeviceBayViewSet.as_view({'get': 'list'}), name='device_devicebays'),
-    url(r'^devices/(?P<pk>\d+)/modules/$', views.NestedModuleViewSet.as_view({'get': 'list'}), name='device_modules'),
+    url(r'^devices/(?P<pk>\d+)/console-ports/$', views.ChildConsolePortViewSet.as_view({'get': 'list'}), name='consoleport-list'),
+    url(r'^devices/(?P<pk>\d+)/console-server-ports/$', views.ChildConsoleServerPortViewSet.as_view({'get': 'list'}), name='consoleserverport-list'),
+    url(r'^devices/(?P<pk>\d+)/power-ports/$', views.NestedPowerPortViewSet.as_view({'get': 'list'}), name='powerport-list'),
+    url(r'^devices/(?P<pk>\d+)/power-outlets/$', views.NestedPowerOutletViewSet.as_view({'get': 'list'}), name='poweroutlet-list'),
+    url(r'^devices/(?P<pk>\d+)/interfaces/$', views.NestedInterfaceViewSet.as_view({'get': 'list'}), name='interface-list'),
+    url(r'^devices/(?P<pk>\d+)/device-bays/$', views.NestedDeviceBayViewSet.as_view({'get': 'list'}), name='devicebay-list'),
+    url(r'^devices/(?P<pk>\d+)/modules/$', views.NestedModuleViewSet.as_view({'get': 'list'}), name='module-list'),
     # TODO: Services
 
     # Console ports
-    url(r'^console-ports/(?P<pk>\d+)/$', views.ConsolePortViewSet.as_view({'get': 'retrieve'}), name='consoleport'),
+    url(r'^console-ports/(?P<pk>\d+)/$', views.ConsolePortViewSet.as_view({'get': 'retrieve'}), name='consoleport-detail'),
 
     # Console server ports
-    url(r'^console-server-ports/(?P<pk>\d+)/$', views.ConsoleServerPortViewSet.as_view({'get': 'retrieve'}), name='consoleserverport'),
+    url(r'^console-server-ports/(?P<pk>\d+)/$', views.ConsoleServerPortViewSet.as_view({'get': 'retrieve'}), name='consoleserverport-detail'),
 
     # Power ports
-    url(r'^power-ports/(?P<pk>\d+)/$', views.PowerPortViewSet.as_view({'get': 'retrieve'}), name='powerport'),
+    url(r'^power-ports/(?P<pk>\d+)/$', views.PowerPortViewSet.as_view({'get': 'retrieve'}), name='powerport-detail'),
 
     # Power outlets
-    url(r'^power-outlets/(?P<pk>\d+)/$', views.PowerOutletViewSet.as_view({'get': 'retrieve'}), name='poweroutlet'),
+    url(r'^power-outlets/(?P<pk>\d+)/$', views.PowerOutletViewSet.as_view({'get': 'retrieve'}), name='poweroutlet-detail'),
 
     # Interfaces
-    url(r'^interfaces/(?P<pk>\d+)/$', views.InterfaceViewSet.as_view({'get': 'retrieve'}), name='interface'),
+    url(r'^interfaces/(?P<pk>\d+)/$', views.InterfaceViewSet.as_view({'get': 'retrieve'}), name='interface-detail'),
     url(r'^interfaces/(?P<pk>\d+)/graphs/$', GraphListView.as_view(), {'type': GRAPH_TYPE_INTERFACE},
         name='interface_graphs'),
 
     # Device bays
-    url(r'^device-bays/(?P<pk>\d+)/$', views.DeviceBayViewSet.as_view({'get': 'retrieve'}), name='devicebay'),
+    url(r'^device-bays/(?P<pk>\d+)/$', views.DeviceBayViewSet.as_view({'get': 'retrieve'}), name='devicebay-detail'),
 
     # Modules
-    url(r'^modules/(?P<pk>\d+)/$', views.ModuleViewSet.as_view({'get': 'retrieve'}), name='module'),
+    url(r'^modules/(?P<pk>\d+)/$', views.ModuleViewSet.as_view({'get': 'retrieve'}), name='module-detail'),
 
     # Miscellaneous
     url(r'^related-connections/$', views.RelatedConnectionsView.as_view(), name='related_connections'),

+ 15 - 16
netbox/dcim/api/views.py

@@ -57,13 +57,9 @@ class RackRoleViewSet(ModelViewSet):
 
 class RackViewSet(CustomFieldModelViewSet):
     queryset = Rack.objects.select_related('site', 'group__site', 'tenant')
+    serializer_class = serializers.RackSerializer
     filter_class = filters.RackFilter
 
-    def get_serializer_class(self):
-        if self.action == 'retrieve':
-            return serializers.RackDetailSerializer
-        return serializers.RackSerializer
-
 
 class RackUnitListView(APIView):
     """
@@ -85,7 +81,10 @@ class RackUnitListView(APIView):
         # Serialize Devices within the rack elevation
         for u in elevation:
             if u['device']:
-                u['device'] = serializers.DeviceNestedSerializer(instance=u['device']).data
+                u['device'] = serializers.NestedDeviceSerializer(
+                    instance=u['device'],
+                    context={'request': request},
+                ).data
 
         return Response(elevation)
 
@@ -105,7 +104,7 @@ class ManufacturerViewSet(ModelViewSet):
 
 class DeviceTypeViewSet(CustomFieldModelViewSet):
     queryset = DeviceType.objects.select_related('manufacturer')
-    filter_class = filters.DeviceTypeFilter
+    serializer_class = serializers.DeviceTypeSerializer
 
 
 #
@@ -150,8 +149,8 @@ class ConsolePortViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin
     serializer_class = serializers.ConsolePortSerializer
 
 
-class NestedConsolePortViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
-    serializer_class = serializers.NestedConsolePortSerializer
+class ChildConsolePortViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
+    serializer_class = serializers.ChildConsoleServerPortSerializer
 
     def get_queryset(self):
         device = get_object_or_404(Device, pk=self.kwargs['pk'])
@@ -167,8 +166,8 @@ class ConsoleServerPortViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyMode
     serializer_class = serializers.ConsoleServerPortSerializer
 
 
-class NestedConsoleServerPortViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
-    serializer_class = serializers.NestedConsoleServerPortSerializer
+class ChildConsoleServerPortViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
+    serializer_class = serializers.ChildConsoleServerPortSerializer
 
     def get_queryset(self):
         device = get_object_or_404(Device, pk=self.kwargs['pk'])
@@ -185,7 +184,7 @@ class PowerPortViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin,
 
 
 class NestedPowerPortViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
-    serializer_class = serializers.NestedPowerPortSerializer
+    serializer_class = serializers.ChildPowerPortSerializer
 
     def get_queryset(self):
         device = get_object_or_404(Device, pk=self.kwargs['pk'])
@@ -202,7 +201,7 @@ class PowerOutletViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin
 
 
 class NestedPowerOutletViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
-    serializer_class = serializers.NestedPowerOutletSerializer
+    serializer_class = serializers.ChildPowerOutletSerializer
 
     def get_queryset(self):
         device = get_object_or_404(Device, pk=self.kwargs['pk'])
@@ -219,7 +218,7 @@ class InterfaceViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin,
 
 
 class NestedInterfaceViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
-    serializer_class = serializers.NestedInterfaceSerializer
+    serializer_class = serializers.ChildInterfaceSerializer
     filter_class = filters.InterfaceFilter
 
     def get_queryset(self):
@@ -238,7 +237,7 @@ class DeviceBayViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin,
 
 
 class NestedDeviceBayViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
-    serializer_class = serializers.NestedDeviceBaySerializer
+    serializer_class = serializers.ChildDeviceBaySerializer
 
     def get_queryset(self):
         device = get_object_or_404(Device, pk=self.kwargs['pk'])
@@ -255,7 +254,7 @@ class ModuleViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, Gen
 
 
 class NestedModuleViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
-    serializer_class = serializers.NestedModuleSerializer
+    serializer_class = serializers.ChildModuleSerializer
 
     def get_queryset(self):
         device = get_object_or_404(Device, pk=self.kwargs['pk'])

+ 8 - 3
netbox/extras/api/views.py

@@ -33,10 +33,12 @@ class CustomFieldModelViewSet(ModelViewSet):
                 custom_field_choices[cfc.id] = cfc.value
         custom_field_choices = custom_field_choices
 
-        return {
+        context = super(CustomFieldModelViewSet, self).get_serializer_context()
+        context.update({
             'custom_fields': custom_fields,
             'custom_field_choices': custom_field_choices,
-        }
+        })
+        return context
 
     def get_queryset(self):
         # Prefetch custom field values
@@ -55,8 +57,11 @@ class GraphListView(generics.ListAPIView):
             GRAPH_TYPE_PROVIDER: Provider,
             GRAPH_TYPE_SITE: Site,
         }
+        obj = get_object_or_404(cls[self.kwargs.get('type')], pk=self.kwargs['pk'])
         context = super(GraphListView, self).get_serializer_context()
-        context.update({'graphed_object': get_object_or_404(cls[self.kwargs.get('type')], pk=self.kwargs['pk'])})
+        context.update({
+            'graphed_object': obj,
+        })
         return context
 
     def get_queryset(self):

+ 64 - 65
netbox/ipam/api/serializers.py

@@ -1,9 +1,9 @@
 from rest_framework import serializers
 
-from dcim.api.serializers import DeviceNestedSerializer, NestedInterfaceSerializer, SiteNestedSerializer
+from dcim.api.serializers import NestedDeviceSerializer, ChildInterfaceSerializer, NestedSiteSerializer
 from extras.api.serializers import CustomFieldSerializer
 from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
-from tenancy.api.serializers import TenantNestedSerializer
+from tenancy.api.serializers import NestedTenantSerializer
 
 
 #
@@ -11,26 +11,18 @@ from tenancy.api.serializers import TenantNestedSerializer
 #
 
 class VRFSerializer(CustomFieldSerializer, serializers.ModelSerializer):
-    tenant = TenantNestedSerializer()
+    tenant = NestedTenantSerializer()
 
     class Meta:
         model = VRF
         fields = ['id', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'custom_fields']
 
 
-class VRFNestedSerializer(VRFSerializer):
+class NestedVRFSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(VRFSerializer.Meta):
-        fields = ['id', 'name', 'rd']
-
-
-class VRFTenantSerializer(VRFSerializer):
-    """
-    Include tenant serializer. Useful for determining tenant inheritance for Prefixes and IPAddresses.
-    """
-
-    class Meta(VRFSerializer.Meta):
-        fields = ['id', 'name', 'rd', 'tenant']
+    class Meta:
+        model = VRF
+        fields = ['id', 'url', 'name', 'rd']
 
 
 #
@@ -44,10 +36,11 @@ class RoleSerializer(serializers.ModelSerializer):
         fields = ['id', 'name', 'slug', 'weight']
 
 
-class RoleNestedSerializer(RoleSerializer):
+class NestedRoleSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(RoleSerializer.Meta):
-        fields = ['id', 'name', 'slug']
+    class Meta:
+        model = Role
+        fields = ['id', 'url', 'name', 'slug']
 
 
 #
@@ -61,10 +54,11 @@ class RIRSerializer(serializers.ModelSerializer):
         fields = ['id', 'name', 'slug', 'is_private']
 
 
-class RIRNestedSerializer(RIRSerializer):
+class NestedRIRSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(RIRSerializer.Meta):
-        fields = ['id', 'name', 'slug']
+    class Meta:
+        model = RIR
+        fields = ['id', 'url', 'name', 'slug']
 
 
 #
@@ -72,17 +66,18 @@ class RIRNestedSerializer(RIRSerializer):
 #
 
 class AggregateSerializer(CustomFieldSerializer, serializers.ModelSerializer):
-    rir = RIRNestedSerializer()
+    rir = NestedRIRSerializer()
 
     class Meta:
         model = Aggregate
         fields = ['id', 'family', 'prefix', 'rir', 'date_added', 'description', 'custom_fields']
 
 
-class AggregateNestedSerializer(AggregateSerializer):
+class NestedAggregateSerializer(serializers.HyperlinkedModelSerializer):
 
     class Meta(AggregateSerializer.Meta):
-        fields = ['id', 'family', 'prefix']
+        model = Aggregate
+        fields = ['id', 'url', 'family', 'prefix']
 
 
 #
@@ -90,17 +85,18 @@ class AggregateNestedSerializer(AggregateSerializer):
 #
 
 class VLANGroupSerializer(serializers.ModelSerializer):
-    site = SiteNestedSerializer()
+    site = NestedSiteSerializer()
 
     class Meta:
         model = VLANGroup
         fields = ['id', 'name', 'slug', 'site']
 
 
-class VLANGroupNestedSerializer(VLANGroupSerializer):
+class NestedVLANGroupSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(VLANGroupSerializer.Meta):
-        fields = ['id', 'name', 'slug']
+    class Meta:
+        model = VLANGroup
+        fields = ['id', 'url', 'name', 'slug']
 
 
 #
@@ -108,21 +104,24 @@ class VLANGroupNestedSerializer(VLANGroupSerializer):
 #
 
 class VLANSerializer(CustomFieldSerializer, serializers.ModelSerializer):
-    site = SiteNestedSerializer()
-    group = VLANGroupNestedSerializer()
-    tenant = TenantNestedSerializer()
-    role = RoleNestedSerializer()
+    site = NestedSiteSerializer()
+    group = NestedVLANGroupSerializer()
+    tenant = NestedTenantSerializer()
+    role = NestedRoleSerializer()
 
     class Meta:
         model = VLAN
-        fields = ['id', 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description', 'display_name',
-                  'custom_fields']
+        fields = [
+            'id', 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description', 'display_name',
+            'custom_fields',
+        ]
 
 
-class VLANNestedSerializer(VLANSerializer):
+class NestedVLANSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(VLANSerializer.Meta):
-        fields = ['id', 'vid', 'name', 'display_name']
+    class Meta:
+        model = VLAN
+        fields = ['id', 'url', 'vid', 'name', 'display_name']
 
 
 #
@@ -130,22 +129,25 @@ class VLANNestedSerializer(VLANSerializer):
 #
 
 class PrefixSerializer(CustomFieldSerializer, serializers.ModelSerializer):
-    site = SiteNestedSerializer()
-    vrf = VRFTenantSerializer()
-    tenant = TenantNestedSerializer()
-    vlan = VLANNestedSerializer()
-    role = RoleNestedSerializer()
+    site = NestedSiteSerializer()
+    vrf = NestedVRFSerializer()
+    tenant = NestedTenantSerializer()
+    vlan = NestedVLANSerializer()
+    role = NestedRoleSerializer()
 
     class Meta:
         model = Prefix
-        fields = ['id', 'family', 'prefix', 'site', 'vrf', 'tenant', 'vlan', 'status', 'role', 'is_pool', 'description',
-                  'custom_fields']
+        fields = [
+            'id', 'family', 'prefix', 'site', 'vrf', 'tenant', 'vlan', 'status', 'role', 'is_pool', 'description',
+            'custom_fields',
+        ]
 
 
-class PrefixNestedSerializer(PrefixSerializer):
+class NestedPrefixSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(PrefixSerializer.Meta):
-        fields = ['id', 'family', 'prefix']
+    class Meta:
+        model = Prefix
+        fields = ['id', 'url', 'family', 'prefix']
 
 
 #
@@ -153,23 +155,26 @@ class PrefixNestedSerializer(PrefixSerializer):
 #
 
 class IPAddressSerializer(CustomFieldSerializer, serializers.ModelSerializer):
-    vrf = VRFTenantSerializer()
-    tenant = TenantNestedSerializer()
-    interface = NestedInterfaceSerializer()
+    vrf = NestedVRFSerializer()
+    tenant = NestedTenantSerializer()
+    interface = ChildInterfaceSerializer()
 
     class Meta:
         model = IPAddress
-        fields = ['id', 'family', 'address', 'vrf', 'tenant', 'status', 'interface', 'description', 'nat_inside',
-                  'nat_outside', 'custom_fields']
+        fields = [
+            'id', 'family', 'address', 'vrf', 'tenant', 'status', 'interface', 'description', 'nat_inside',
+            'nat_outside', 'custom_fields',
+        ]
 
 
-class IPAddressNestedSerializer(IPAddressSerializer):
+class NestedIPAddressSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(IPAddressSerializer.Meta):
-        fields = ['id', 'family', 'address']
+    class Meta:
+        model = IPAddress
+        fields = ['id', 'url', 'family', 'address']
 
-IPAddressSerializer._declared_fields['nat_inside'] = IPAddressNestedSerializer()
-IPAddressSerializer._declared_fields['nat_outside'] = IPAddressNestedSerializer()
+IPAddressSerializer._declared_fields['nat_inside'] = NestedIPAddressSerializer()
+IPAddressSerializer._declared_fields['nat_outside'] = NestedIPAddressSerializer()
 
 
 #
@@ -177,15 +182,9 @@ IPAddressSerializer._declared_fields['nat_outside'] = IPAddressNestedSerializer(
 #
 
 class ServiceSerializer(serializers.ModelSerializer):
-    device = DeviceNestedSerializer()
-    ipaddresses = IPAddressNestedSerializer(many=True)
+    device = NestedDeviceSerializer()
+    ipaddresses = NestedIPAddressSerializer(many=True)
 
     class Meta:
         model = Service
         fields = ['id', 'device', 'name', 'port', 'protocol', 'ipaddresses', 'description']
-
-
-class ServiceNestedSerializer(ServiceSerializer):
-
-    class Meta(ServiceSerializer.Meta):
-        fields = ['id', 'name', 'port', 'protocol']

+ 6 - 6
netbox/netbox/urls.py

@@ -26,12 +26,12 @@ _patterns = [
     url(r'^profile/', include('users.urls', namespace='users')),
 
     # API
-    url(r'^api/circuits/', include('circuits.api.urls', namespace='circuits-api')),
-    url(r'^api/dcim/', include('dcim.api.urls', namespace='dcim-api')),
-    url(r'^api/ipam/', include('ipam.api.urls', namespace='ipam-api')),
-    url(r'^api/secrets/', include('secrets.api.urls', namespace='secrets-api')),
-    url(r'^api/tenancy/', include('tenancy.api.urls', namespace='tenancy-api')),
-    url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework')),
+    url(r'^api/circuits/', include('circuits.api.urls')),
+    url(r'^api/dcim/', include('dcim.api.urls')),
+    url(r'^api/ipam/', include('ipam.api.urls')),
+    url(r'^api/secrets/', include('secrets.api.urls')),
+    url(r'^api/tenancy/', include('tenancy.api.urls')),
+    url(r'^api-auth/', include('rest_framework.urls')),
 
     # Error testing
     url(r'^500/$', trigger_500),

+ 7 - 21
netbox/secrets/api/serializers.py

@@ -1,7 +1,6 @@
 from rest_framework import serializers
 
-from dcim.models import Device
-from ipam.api.serializers import IPAddressNestedSerializer
+from dcim.api.serializers import NestedDeviceSerializer
 from secrets.models import Secret, SecretRole
 
 
@@ -16,34 +15,21 @@ class SecretRoleSerializer(serializers.ModelSerializer):
         fields = ['id', 'name', 'slug']
 
 
-class SecretRoleNestedSerializer(SecretRoleSerializer):
+class NestedSecretRoleSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(SecretRoleSerializer.Meta):
-        pass
+    class Meta:
+        model = SecretRole
+        fields = ['id', 'url', 'name', 'slug']
 
 
 #
 # Secrets
 #
 
-class SecretDeviceSerializer(serializers.ModelSerializer):
-    primary_ip = IPAddressNestedSerializer()
-
-    class Meta:
-        model = Device
-        fields = ['id', 'name', 'primary_ip']
-
-
 class SecretSerializer(serializers.ModelSerializer):
-    device = SecretDeviceSerializer()
-    role = SecretRoleNestedSerializer()
+    device = NestedDeviceSerializer()
+    role = NestedSecretRoleSerializer()
 
     class Meta:
         model = Secret
         fields = ['id', 'device', 'role', 'name', 'plaintext', 'hash', 'created', 'last_updated']
-
-
-class SecretNestedSerializer(SecretSerializer):
-
-    class Meta(SecretSerializer.Meta):
-        fields = ['id', 'name']

+ 9 - 7
netbox/tenancy/api/serializers.py

@@ -15,10 +15,11 @@ class TenantGroupSerializer(serializers.ModelSerializer):
         fields = ['id', 'name', 'slug']
 
 
-class TenantGroupNestedSerializer(TenantGroupSerializer):
+class NestedTenantGroupSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(TenantGroupSerializer.Meta):
-        pass
+    class Meta:
+        model = TenantGroup
+        fields = ['id', 'url', 'name', 'slug']
 
 
 #
@@ -26,14 +27,15 @@ class TenantGroupNestedSerializer(TenantGroupSerializer):
 #
 
 class TenantSerializer(CustomFieldSerializer, serializers.ModelSerializer):
-    group = TenantGroupNestedSerializer()
+    group = NestedTenantGroupSerializer()
 
     class Meta:
         model = Tenant
         fields = ['id', 'name', 'slug', 'group', 'description', 'comments', 'custom_fields']
 
 
-class TenantNestedSerializer(TenantSerializer):
+class NestedTenantSerializer(serializers.HyperlinkedModelSerializer):
 
-    class Meta(TenantSerializer.Meta):
-        fields = ['id', 'name', 'slug']
+    class Meta:
+        model = Tenant
+        fields = ['id', 'url', 'name', 'slug']