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

Removed all device-specific API endpoints

Jeremy Stretch 9 лет назад
Родитель
Сommit
77e5450746

+ 2 - 2
netbox/circuits/api/serializers.py

@@ -1,7 +1,7 @@
 from rest_framework import serializers
 from rest_framework import serializers
 
 
 from circuits.models import Provider, Circuit, CircuitTermination, CircuitType
 from circuits.models import Provider, Circuit, CircuitTermination, CircuitType
-from dcim.api.serializers import NestedSiteSerializer, DeviceInterfaceSerializer
+from dcim.api.serializers import NestedSiteSerializer, InterfaceSerializer
 from extras.api.serializers import CustomFieldValueSerializer
 from extras.api.serializers import CustomFieldValueSerializer
 from tenancy.api.serializers import NestedTenantSerializer
 from tenancy.api.serializers import NestedTenantSerializer
 
 
@@ -63,7 +63,7 @@ class NestedCircuitTypeSerializer(serializers.ModelSerializer):
 
 
 class CircuitTerminationSerializer(serializers.ModelSerializer):
 class CircuitTerminationSerializer(serializers.ModelSerializer):
     site = NestedSiteSerializer()
     site = NestedSiteSerializer()
-    interface = DeviceInterfaceSerializer()
+    interface = InterfaceSerializer()
 
 
     class Meta:
     class Meta:
         model = CircuitTermination
         model = CircuitTermination

+ 49 - 68
netbox/dcim/api/serializers.py

@@ -345,20 +345,18 @@ class WritableDeviceSerializer(serializers.ModelSerializer):
 #
 #
 
 
 class ConsoleServerPortSerializer(serializers.ModelSerializer):
 class ConsoleServerPortSerializer(serializers.ModelSerializer):
-    device = NestedDeviceSerializer(read_only=True)
+    device = NestedDeviceSerializer()
 
 
     class Meta:
     class Meta:
         model = ConsoleServerPort
         model = ConsoleServerPort
         fields = ['id', 'device', 'name', 'connected_console']
         fields = ['id', 'device', 'name', 'connected_console']
 
 
 
 
-class DeviceConsoleServerPortSerializer(serializers.ModelSerializer):
-    url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleserverport-detail')
+class WritableConsoleServerPortSerializer(serializers.ModelSerializer):
 
 
     class Meta:
     class Meta:
         model = ConsoleServerPort
         model = ConsoleServerPort
-        fields = ['id', 'url', 'name', 'connected_console']
-        read_only_fields = ['connected_console']
+        fields = ['id', 'device', 'name', 'connected_console']
 
 
 
 
 #
 #
@@ -366,7 +364,7 @@ class DeviceConsoleServerPortSerializer(serializers.ModelSerializer):
 #
 #
 
 
 class ConsolePortSerializer(serializers.ModelSerializer):
 class ConsolePortSerializer(serializers.ModelSerializer):
-    device = NestedDeviceSerializer(read_only=True)
+    device = NestedDeviceSerializer()
     cs_port = ConsoleServerPortSerializer()
     cs_port = ConsoleServerPortSerializer()
 
 
     class Meta:
     class Meta:
@@ -374,13 +372,11 @@ class ConsolePortSerializer(serializers.ModelSerializer):
         fields = ['id', 'device', 'name', 'cs_port', 'connection_status']
         fields = ['id', 'device', 'name', 'cs_port', 'connection_status']
 
 
 
 
-class DeviceConsolePortSerializer(serializers.ModelSerializer):
-    url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleport-detail')
+class WritableConsolePortSerializer(serializers.ModelSerializer):
 
 
     class Meta:
     class Meta:
         model = ConsolePort
         model = ConsolePort
-        fields = ['id', 'url', 'name', 'cs_port', 'connection_status']
-        read_only_fields = ['cs_port', 'connection_status']
+        fields = ['id', 'device', 'name', 'cs_port', 'connection_status']
 
 
 
 
 #
 #
@@ -388,20 +384,18 @@ class DeviceConsolePortSerializer(serializers.ModelSerializer):
 #
 #
 
 
 class PowerOutletSerializer(serializers.ModelSerializer):
 class PowerOutletSerializer(serializers.ModelSerializer):
-    device = NestedDeviceSerializer(read_only=True)
+    device = NestedDeviceSerializer()
 
 
     class Meta:
     class Meta:
         model = PowerOutlet
         model = PowerOutlet
         fields = ['id', 'device', 'name', 'connected_port']
         fields = ['id', 'device', 'name', 'connected_port']
 
 
 
 
-class DevicePowerOutletSerializer(serializers.ModelSerializer):
-    url = serializers.HyperlinkedIdentityField(view_name='dcim-api:poweroutlet-detail')
+class WritablePowerOutletSerializer(serializers.ModelSerializer):
 
 
     class Meta:
     class Meta:
         model = PowerOutlet
         model = PowerOutlet
-        fields = ['id', 'url', 'name', 'connected_port']
-        read_only_fields = ['connected_port']
+        fields = ['id', 'device', 'name', 'connected_port']
 
 
 
 
 #
 #
@@ -409,7 +403,7 @@ class DevicePowerOutletSerializer(serializers.ModelSerializer):
 #
 #
 
 
 class PowerPortSerializer(serializers.ModelSerializer):
 class PowerPortSerializer(serializers.ModelSerializer):
-    device = NestedDeviceSerializer(read_only=True)
+    device = NestedDeviceSerializer()
     power_outlet = PowerOutletSerializer()
     power_outlet = PowerOutletSerializer()
 
 
     class Meta:
     class Meta:
@@ -417,13 +411,11 @@ class PowerPortSerializer(serializers.ModelSerializer):
         fields = ['id', 'device', 'name', 'power_outlet', 'connection_status']
         fields = ['id', 'device', 'name', 'power_outlet', 'connection_status']
 
 
 
 
-class DevicePowerPortSerializer(serializers.ModelSerializer):
-    url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerport-detail')
+class WritablePowerPortSerializer(serializers.ModelSerializer):
 
 
     class Meta:
     class Meta:
         model = PowerPort
         model = PowerPort
-        fields = ['id', 'url', 'name', 'power_outlet', 'connection_status']
-        read_only_fields = ['power_outlet', 'connection_status']
+        fields = ['id', 'device', 'name', 'power_outlet', 'connection_status']
 
 
 
 
 #
 #
@@ -432,7 +424,7 @@ class DevicePowerPortSerializer(serializers.ModelSerializer):
 
 
 
 
 class InterfaceSerializer(serializers.ModelSerializer):
 class InterfaceSerializer(serializers.ModelSerializer):
-    device = NestedDeviceSerializer(read_only=True)
+    device = NestedDeviceSerializer()
     connection = serializers.SerializerMethodField(read_only=True)
     connection = serializers.SerializerMethodField(read_only=True)
     connected_interface = serializers.SerializerMethodField(read_only=True)
     connected_interface = serializers.SerializerMethodField(read_only=True)
 
 
@@ -463,46 +455,11 @@ class PeerInterfaceSerializer(serializers.ModelSerializer):
         fields = ['id', 'url', 'device', 'name', 'form_factor', 'mac_address', 'mgmt_only', 'description']
         fields = ['id', 'url', 'device', 'name', 'form_factor', 'mac_address', 'mgmt_only', 'description']
 
 
 
 
-class DeviceInterfaceSerializer(serializers.ModelSerializer):
-    url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interface-detail')
-    connection = serializers.SerializerMethodField()
+class WritableInterfaceSerializer(serializers.ModelSerializer):
 
 
     class Meta:
     class Meta:
         model = Interface
         model = Interface
-        fields = ['id', 'url', 'name', 'form_factor', 'mac_address', 'mgmt_only', 'description', 'connection']
-
-    def get_connection(self, obj):
-        if obj.connection:
-            return NestedInterfaceConnectionSerializer(obj.connection, context=self.context).data
-        return None
-
-
-#
-# Interface connections
-#
-
-class InterfaceConnectionSerializer(serializers.ModelSerializer):
-    interface_a = PeerInterfaceSerializer()
-    interface_b = PeerInterfaceSerializer()
-
-    class Meta:
-        model = InterfaceConnection
-        fields = ['id', 'interface_a', 'interface_b', 'connection_status']
-
-
-class NestedInterfaceConnectionSerializer(serializers.ModelSerializer):
-    url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interfaceconnection-detail')
-
-    class Meta:
-        model = InterfaceConnection
-        fields = ['id', 'url', 'connection_status']
-
-
-class WritableInterfaceConnectionSerializer(serializers.ModelSerializer):
-
-    class Meta:
-        model = InterfaceConnection
-        fields = ['id', 'interface_a', 'interface_b', 'connection_status']
+        fields = ['id', 'device', 'name', 'form_factor', 'mac_address', 'mgmt_only', 'description']
 
 
 
 
 #
 #
@@ -510,7 +467,7 @@ class WritableInterfaceConnectionSerializer(serializers.ModelSerializer):
 #
 #
 
 
 class DeviceBaySerializer(serializers.ModelSerializer):
 class DeviceBaySerializer(serializers.ModelSerializer):
-    device = NestedDeviceSerializer(read_only=True)
+    device = NestedDeviceSerializer()
     installed_device = NestedDeviceSerializer()
     installed_device = NestedDeviceSerializer()
 
 
     class Meta:
     class Meta:
@@ -518,13 +475,11 @@ class DeviceBaySerializer(serializers.ModelSerializer):
         fields = ['id', 'device', 'name', 'installed_device']
         fields = ['id', 'device', 'name', 'installed_device']
 
 
 
 
-class DeviceDeviceBaySerializer(serializers.ModelSerializer):
-    url = serializers.HyperlinkedIdentityField(view_name='dcim-api:devicebay-detail')
+class WritableDeviceBaySerializer(serializers.ModelSerializer):
 
 
     class Meta:
     class Meta:
         model = DeviceBay
         model = DeviceBay
-        fields = ['id', 'url', 'name', 'installed_device']
-        read_only_fields = ['installed_device']
+        fields = ['id', 'device', 'name']
 
 
 
 
 #
 #
@@ -532,7 +487,7 @@ class DeviceDeviceBaySerializer(serializers.ModelSerializer):
 #
 #
 
 
 class ModuleSerializer(serializers.ModelSerializer):
 class ModuleSerializer(serializers.ModelSerializer):
-    device = NestedDeviceSerializer(read_only=True)
+    device = NestedDeviceSerializer()
     manufacturer = NestedManufacturerSerializer()
     manufacturer = NestedManufacturerSerializer()
 
 
     class Meta:
     class Meta:
@@ -540,10 +495,36 @@ class ModuleSerializer(serializers.ModelSerializer):
         fields = ['id', 'device', 'parent', 'name', 'manufacturer', 'part_id', 'serial', 'discovered']
         fields = ['id', 'device', 'parent', 'name', 'manufacturer', 'part_id', 'serial', 'discovered']
 
 
 
 
-class DeviceModuleSerializer(serializers.ModelSerializer):
-    url = serializers.HyperlinkedIdentityField(view_name='dcim-api:module-detail')
-    manufacturer = NestedManufacturerSerializer()
+class WritableModuleSerializer(serializers.ModelSerializer):
 
 
     class Meta:
     class Meta:
         model = Module
         model = Module
-        fields = ['id', 'url', 'name', 'manufacturer', 'part_id', 'serial', 'discovered']
+        fields = ['id', 'device', 'parent', 'name', 'manufacturer', 'part_id', 'serial', 'discovered']
+
+
+#
+# Interface connections
+#
+
+class InterfaceConnectionSerializer(serializers.ModelSerializer):
+    interface_a = PeerInterfaceSerializer()
+    interface_b = PeerInterfaceSerializer()
+
+    class Meta:
+        model = InterfaceConnection
+        fields = ['id', 'interface_a', 'interface_b', 'connection_status']
+
+
+class NestedInterfaceConnectionSerializer(serializers.ModelSerializer):
+    url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interfaceconnection-detail')
+
+    class Meta:
+        model = InterfaceConnection
+        fields = ['id', 'url', 'connection_status']
+
+
+class WritableInterfaceConnectionSerializer(serializers.ModelSerializer):
+
+    class Meta:
+        model = InterfaceConnection
+        fields = ['id', 'interface_a', 'interface_b', 'connection_status']

+ 7 - 15
netbox/dcim/api/urls.py

@@ -3,7 +3,7 @@ from django.conf.urls import include, url
 from rest_framework import routers
 from rest_framework import routers
 
 
 from extras.api.views import TopologyMapView
 from extras.api.views import TopologyMapView
-from ipam.api.views import ServiceViewSet, DeviceServiceViewSet
+from ipam.api.views import ServiceViewSet
 from . import views
 from . import views
 
 
 
 
@@ -21,37 +21,29 @@ router.register(r'racks', views.RackViewSet)
 router.register(r'manufacturers', views.ManufacturerViewSet)
 router.register(r'manufacturers', views.ManufacturerViewSet)
 router.register(r'device-types', views.DeviceTypeViewSet)
 router.register(r'device-types', views.DeviceTypeViewSet)
 
 
+# TODO: Device type components
+
 # Devices
 # Devices
 router.register(r'device-roles', views.DeviceRoleViewSet)
 router.register(r'device-roles', views.DeviceRoleViewSet)
 router.register(r'platforms', views.PlatformViewSet)
 router.register(r'platforms', views.PlatformViewSet)
 router.register(r'devices', views.DeviceViewSet)
 router.register(r'devices', views.DeviceViewSet)
+
+# Device components
 router.register(r'console-ports', views.ConsolePortViewSet)
 router.register(r'console-ports', views.ConsolePortViewSet)
 router.register(r'console-server-ports', views.ConsoleServerPortViewSet)
 router.register(r'console-server-ports', views.ConsoleServerPortViewSet)
 router.register(r'power-ports', views.PowerPortViewSet)
 router.register(r'power-ports', views.PowerPortViewSet)
 router.register(r'power-outlets', views.PowerOutletViewSet)
 router.register(r'power-outlets', views.PowerOutletViewSet)
 router.register(r'interfaces', views.InterfaceViewSet)
 router.register(r'interfaces', views.InterfaceViewSet)
-router.register(r'interface-connections', views.InterfaceConnectionViewSet)
 router.register(r'device-bays', views.DeviceBayViewSet)
 router.register(r'device-bays', views.DeviceBayViewSet)
 router.register(r'modules', views.ModuleViewSet)
 router.register(r'modules', views.ModuleViewSet)
 router.register(r'services', ServiceViewSet)
 router.register(r'services', ServiceViewSet)
 
 
-# TODO: Device type components
-
-# Device components
-device_router = routers.DefaultRouter()
-device_router.register(r'console-ports', views.DeviceConsolePortViewSet, base_name='consoleport')
-device_router.register(r'console-server-ports', views.DeviceConsoleServerPortViewSet, base_name='consoleserverport')
-device_router.register(r'power-ports', views.DevicePowerPortViewSet, base_name='powerport')
-device_router.register(r'power-outlets', views.DevicePowerOutletViewSet, base_name='poweroutlet')
-device_router.register(r'interfaces', views.DeviceInterfaceViewSet, base_name='interface')
-device_router.register(r'device-bays', views.DeviceDeviceBayViewSet, base_name='devicebay')
-device_router.register(r'modules', views.DeviceModuleViewSet, base_name='module')
-device_router.register(r'services', DeviceServiceViewSet, base_name='service')
+# Interface connections
+router.register(r'interface-connections', views.InterfaceConnectionViewSet)
 
 
 urlpatterns = [
 urlpatterns = [
 
 
     url(r'', include(router.urls)),
     url(r'', include(router.urls)),
-    url(r'^devices/(?P<pk>\d+)/', include(device_router.urls)),
 
 
     # Miscellaneous
     # Miscellaneous
     url(r'^related-connections/$', views.RelatedConnectionsView.as_view(), name='related_connections'),
     url(r'^related-connections/$', views.RelatedConnectionsView.as_view(), name='related_connections'),

+ 27 - 132
netbox/dcim/api/views.py

@@ -1,11 +1,8 @@
 from rest_framework.decorators import detail_route
 from rest_framework.decorators import detail_route
-from rest_framework.mixins import (
-    CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin,
-)
 from rest_framework.response import Response
 from rest_framework.response import Response
 from rest_framework.settings import api_settings
 from rest_framework.settings import api_settings
 from rest_framework.views import APIView
 from rest_framework.views import APIView
-from rest_framework.viewsets import GenericViewSet, ModelViewSet
+from rest_framework.viewsets import ModelViewSet
 
 
 from django.conf import settings
 from django.conf import settings
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes.models import ContentType
@@ -175,101 +172,42 @@ class DeviceViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
 
 
 
 
 #
 #
-# Console Ports
+# Device components
 #
 #
 
 
-class ConsolePortViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, WritableSerializerMixin,
-                         GenericViewSet):
-    queryset = ConsolePort.objects.select_related('cs_port')
+class ConsolePortViewSet(WritableSerializerMixin, ModelViewSet):
+    queryset = ConsolePort.objects.select_related('device', 'cs_port__device')
     serializer_class = serializers.ConsolePortSerializer
     serializer_class = serializers.ConsolePortSerializer
+    write_serializer_class= serializers.WritableConsolePortSerializer
+    filter_class = filters.ConsolePortFilter
 
 
 
 
-class DeviceConsolePortViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
-    serializer_class = serializers.DeviceConsolePortSerializer
-
-    def get_queryset(self):
-        device = get_object_or_404(Device, pk=self.kwargs['pk'])
-        return ConsolePort.objects.filter(device=device).select_related('cs_port')
-
-    def perform_create(self, serializer):
-        device = get_object_or_404(Device, pk=self.kwargs['pk'])
-        serializer.save(device=device)
-
-
-#
-# Console Server Ports
-#
-
-class ConsoleServerPortViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, WritableSerializerMixin,
-                               GenericViewSet):
-    queryset = ConsoleServerPort.objects.select_related('connected_console')
+class ConsoleServerPortViewSet(WritableSerializerMixin, ModelViewSet):
+    queryset = ConsoleServerPort.objects.select_related('device', 'connected_console__device')
     serializer_class = serializers.ConsoleServerPortSerializer
     serializer_class = serializers.ConsoleServerPortSerializer
+    write_serializer_class= serializers.WritableConsoleServerPortSerializer
+    filter_class = filters.ConsoleServerPortFilter
 
 
 
 
-class DeviceConsoleServerPortViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
-    serializer_class = serializers.DeviceConsoleServerPortSerializer
-
-    def get_queryset(self):
-        device = get_object_or_404(Device, pk=self.kwargs['pk'])
-        return ConsoleServerPort.objects.filter(device=device).select_related('connected_console')
-
-    def perform_create(self, serializer):
-        device = get_object_or_404(Device, pk=self.kwargs['pk'])
-        serializer.save(device=device)
-
-
-#
-# Power Ports
-#
-
-class PowerPortViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, WritableSerializerMixin,
-                       GenericViewSet):
-    queryset = PowerPort.objects.select_related('power_outlet')
+class PowerPortViewSet(WritableSerializerMixin, ModelViewSet):
+    queryset = PowerPort.objects.select_related('device', 'power_outlet__device')
     serializer_class = serializers.PowerPortSerializer
     serializer_class = serializers.PowerPortSerializer
+    write_serializer_class= serializers.WritablePowerPortSerializer
+    filter_class = filters.PowerPortFilter
 
 
 
 
-class DevicePowerPortViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
-    serializer_class = serializers.DevicePowerPortSerializer
-
-    def get_queryset(self):
-        device = get_object_or_404(Device, pk=self.kwargs['pk'])
-        return PowerPort.objects.filter(device=device).select_related('power_outlet')
-
-    def perform_create(self, serializer):
-        device = get_object_or_404(Device, pk=self.kwargs['pk'])
-        serializer.save(device=device)
-
-
-#
-# Power Outlets
-#
-
-class PowerOutletViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, WritableSerializerMixin,
-                         GenericViewSet):
-    queryset = PowerOutlet.objects.select_related('connected_port')
+class PowerOutletViewSet(WritableSerializerMixin, ModelViewSet):
+    queryset = PowerOutlet.objects.select_related('device', 'connected_port__device')
     serializer_class = serializers.PowerOutletSerializer
     serializer_class = serializers.PowerOutletSerializer
+    write_serializer_class= serializers.WritablePowerOutletSerializer
+    filter_class = filters.PowerOutletFilter
 
 
 
 
-class DevicePowerOutletViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
-    serializer_class = serializers.DevicePowerOutletSerializer
-
-    def get_queryset(self):
-        device = get_object_or_404(Device, pk=self.kwargs['pk'])
-        return PowerOutlet.objects.filter(device=device).select_related('connected_port')
-
-    def perform_create(self, serializer):
-        device = get_object_or_404(Device, pk=self.kwargs['pk'])
-        serializer.save(device=device)
-
-
-#
-# Interfaces
-#
-
-class InterfaceViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, WritableSerializerMixin,
-                       GenericViewSet):
+class InterfaceViewSet(WritableSerializerMixin, ModelViewSet):
     queryset = Interface.objects.select_related('device')
     queryset = Interface.objects.select_related('device')
     serializer_class = serializers.InterfaceSerializer
     serializer_class = serializers.InterfaceSerializer
+    write_serializer_class= serializers.WritableInterfaceSerializer
+    filter_class = filters.InterfaceFilter
 
 
     @detail_route()
     @detail_route()
     def graphs(self, request, pk=None):
     def graphs(self, request, pk=None):
@@ -279,61 +217,18 @@ class InterfaceViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin,
         return Response(serializer.data)
         return Response(serializer.data)
 
 
 
 
-class DeviceInterfaceViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
-    serializer_class = serializers.DeviceInterfaceSerializer
-    filter_class = filters.InterfaceFilter
-
-    def get_queryset(self):
-        device = get_object_or_404(Device, pk=self.kwargs['pk'])
-        return Interface.objects.order_naturally(device.device_type.interface_ordering).filter(device=device)\
-            .select_related('connected_as_a', 'connected_as_b', 'circuit_termination')
-
-    def perform_create(self, serializer):
-        device = get_object_or_404(Device, pk=self.kwargs['pk'])
-        serializer.save(device=device)
-
-
-#
-# Device bays
-#
-
-class DeviceBayViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, WritableSerializerMixin,
-                       GenericViewSet):
+class DeviceBayViewSet(WritableSerializerMixin, ModelViewSet):
     queryset = DeviceBay.objects.select_related('installed_device')
     queryset = DeviceBay.objects.select_related('installed_device')
     serializer_class = serializers.DeviceBaySerializer
     serializer_class = serializers.DeviceBaySerializer
+    write_serializer_class= serializers.WritableDeviceBaySerializer
+    filter_class = filters.DeviceBayFilter
 
 
 
 
-class DeviceDeviceBayViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
-    serializer_class = serializers.DeviceDeviceBaySerializer
-
-    def get_queryset(self):
-        device = get_object_or_404(Device, pk=self.kwargs['pk'])
-        return DeviceBay.objects.filter(device=device).select_related('installed_device')
-
-    def perform_create(self, serializer):
-        device = get_object_or_404(Device, pk=self.kwargs['pk'])
-        serializer.save(device=device)
-
-
-#
-# Modules
-#
-
-class ModuleViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, WritableSerializerMixin, GenericViewSet):
+class ModuleViewSet(WritableSerializerMixin, ModelViewSet):
     queryset = Module.objects.select_related('device', 'manufacturer')
     queryset = Module.objects.select_related('device', 'manufacturer')
     serializer_class = serializers.ModuleSerializer
     serializer_class = serializers.ModuleSerializer
-
-
-class DeviceModuleViewSet(CreateModelMixin, ListModelMixin, GenericViewSet):
-    serializer_class = serializers.DeviceModuleSerializer
-
-    def get_queryset(self):
-        device = get_object_or_404(Device, pk=self.kwargs['pk'])
-        return Module.objects.filter(device=device).select_related('device', 'manufacturer')
-
-    def perform_create(self, serializer):
-        device = get_object_or_404(Device, pk=self.kwargs['pk'])
-        serializer.save(device=device)
+    write_serializer_class= serializers.WritableModuleSerializer
+    filter_class = filters.ModuleFilter
 
 
 
 
 #
 #

+ 38 - 2
netbox/dcim/filters.py

@@ -7,8 +7,8 @@ from extras.filters import CustomFieldFilterSet
 from tenancy.models import Tenant
 from tenancy.models import Tenant
 from utilities.filters import NullableModelMultipleChoiceFilter
 from utilities.filters import NullableModelMultipleChoiceFilter
 from .models import (
 from .models import (
-    ConsolePort, ConsoleServerPort, Device, DeviceRole, DeviceType, Interface, InterfaceConnection, Manufacturer,
-    Platform, PowerOutlet, PowerPort, Rack, RackGroup, RackRole, Site,
+    ConsolePort, ConsoleServerPort, Device, DeviceBay, DeviceRole, DeviceType, Interface, InterfaceConnection,
+    Manufacturer, Module, Platform, PowerOutlet, PowerPort, Rack, RackGroup, RackRole, Site,
 )
 )
 
 
 
 
@@ -368,6 +368,42 @@ class InterfaceFilter(django_filters.FilterSet):
         fields = ['name']
         fields = ['name']
 
 
 
 
+class DeviceBayFilter(django_filters.FilterSet):
+    device_id = django_filters.ModelMultipleChoiceFilter(
+        name='device',
+        queryset=Device.objects.all(),
+        label='Device (ID)',
+    )
+    device = django_filters.ModelMultipleChoiceFilter(
+        name='device',
+        queryset=Device.objects.all(),
+        to_field_name='name',
+        label='Device (name)',
+    )
+
+    class Meta:
+        model = DeviceBay
+        fields = ['name']
+
+
+class ModuleFilter(django_filters.FilterSet):
+    device_id = django_filters.ModelMultipleChoiceFilter(
+        name='device',
+        queryset=Device.objects.all(),
+        label='Device (ID)',
+    )
+    device = django_filters.ModelMultipleChoiceFilter(
+        name='device',
+        queryset=Device.objects.all(),
+        to_field_name='name',
+        label='Device (name)',
+    )
+
+    class Meta:
+        model = Module
+        fields = ['name']
+
+
 class ConsoleConnectionFilter(django_filters.FilterSet):
 class ConsoleConnectionFilter(django_filters.FilterSet):
     site = django_filters.MethodFilter(
     site = django_filters.MethodFilter(
         action='filter_site',
         action='filter_site',

+ 4 - 6
netbox/ipam/api/serializers.py

@@ -1,6 +1,6 @@
 from rest_framework import serializers
 from rest_framework import serializers
 
 
-from dcim.api.serializers import NestedDeviceSerializer, DeviceInterfaceSerializer, NestedSiteSerializer
+from dcim.api.serializers import NestedDeviceSerializer, InterfaceSerializer, NestedSiteSerializer
 from extras.api.serializers import CustomFieldValueSerializer
 from extras.api.serializers import CustomFieldValueSerializer
 from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
 from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
 from tenancy.api.serializers import NestedTenantSerializer
 from tenancy.api.serializers import NestedTenantSerializer
@@ -207,7 +207,7 @@ class WritablePrefixSerializer(serializers.ModelSerializer):
 class IPAddressSerializer(serializers.ModelSerializer):
 class IPAddressSerializer(serializers.ModelSerializer):
     vrf = NestedVRFSerializer()
     vrf = NestedVRFSerializer()
     tenant = NestedTenantSerializer()
     tenant = NestedTenantSerializer()
-    interface = DeviceInterfaceSerializer()
+    interface = InterfaceSerializer()
     custom_field_values = CustomFieldValueSerializer(many=True)
     custom_field_values = CustomFieldValueSerializer(many=True)
 
 
     class Meta:
     class Meta:
@@ -249,10 +249,8 @@ class ServiceSerializer(serializers.ModelSerializer):
         fields = ['id', 'device', 'name', 'port', 'protocol', 'ipaddresses', 'description']
         fields = ['id', 'device', 'name', 'port', 'protocol', 'ipaddresses', 'description']
 
 
 
 
-class DeviceServiceSerializer(serializers.ModelSerializer):
-    url = serializers.HyperlinkedIdentityField(view_name='ipam-api:service-detail')
-    ipaddresses = NestedIPAddressSerializer(many=True)
+class WritableServiceSerializer(serializers.ModelSerializer):
 
 
     class Meta:
     class Meta:
         model = Service
         model = Service
-        fields = ['id', 'url', 'name', 'port', 'protocol', 'ipaddresses', 'description']
+        fields = ['id', 'device', 'name', 'port', 'protocol', 'ipaddresses', 'description']

+ 3 - 16
netbox/ipam/api/views.py

@@ -1,11 +1,5 @@
-from django.shortcuts import get_object_or_404
+from rest_framework.viewsets import ModelViewSet
 
 
-from rest_framework.mixins import (
-    CreateModelMixin, DestroyModelMixin, ListModelMixin, RetrieveModelMixin, UpdateModelMixin,
-)
-from rest_framework.viewsets import GenericViewSet, ModelViewSet
-
-from dcim.models import Device
 from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
 from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, Service, VLAN, VLANGroup, VRF
 from ipam import filters
 from ipam import filters
 from extras.api.views import CustomFieldModelViewSet
 from extras.api.views import CustomFieldModelViewSet
@@ -101,14 +95,7 @@ class VLANViewSet(WritableSerializerMixin, CustomFieldModelViewSet):
 # Services
 # Services
 #
 #
 
 
-class ServiceViewSet(RetrieveModelMixin, UpdateModelMixin, DestroyModelMixin, WritableSerializerMixin, GenericViewSet):
+class ServiceViewSet(WritableSerializerMixin, ModelViewSet):
     queryset = Service.objects.select_related('device')
     queryset = Service.objects.select_related('device')
     serializer_class = serializers.ServiceSerializer
     serializer_class = serializers.ServiceSerializer
-
-
-class DeviceServiceViewSet(CreateModelMixin, ListModelMixin, WritableSerializerMixin, GenericViewSet):
-    serializer_class = serializers.DeviceServiceSerializer
-
-    def get_queryset(self):
-        device = get_object_or_404(Device, pk=self.kwargs['pk'])
-        return Service.objects.filter(device=device).select_related('device')
+    write_serializer_class = serializers.WritableServiceSerializer