From e616aad9117f33bbf044ae3837a2a1290144169b Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Fri, 5 Jun 2020 15:48:36 -0400 Subject: [PATCH] Fixes #4725: Fix "brief" rendering of various REST API endpoints --- docs/release-notes/version-2.8.md | 1 + netbox/dcim/api/nested_serializers.py | 123 ++++++++++++++++++------ netbox/extras/api/nested_serializers.py | 44 ++++++++- netbox/ipam/api/nested_serializers.py | 32 ++++-- 4 files changed, 155 insertions(+), 45 deletions(-) diff --git a/docs/release-notes/version-2.8.md b/docs/release-notes/version-2.8.md index 6bb395524..f9b02db8d 100644 --- a/docs/release-notes/version-2.8.md +++ b/docs/release-notes/version-2.8.md @@ -10,6 +10,7 @@ * [#4702](https://github.com/netbox-community/netbox/issues/4702) - Catch IntegrityError exception when adding a non-unique secret * [#4707](https://github.com/netbox-community/netbox/issues/4707) - Fix `prefix_count` population on VLAN API serializer +* [#4725](https://github.com/netbox-community/netbox/issues/4725) - Fix "brief" rendering of various REST API endpoints --- diff --git a/netbox/dcim/api/nested_serializers.py b/netbox/dcim/api/nested_serializers.py index bb2d61faa..a8d413d37 100644 --- a/netbox/dcim/api/nested_serializers.py +++ b/netbox/dcim/api/nested_serializers.py @@ -1,32 +1,35 @@ from rest_framework import serializers from dcim.constants import CONNECTION_STATUS_CHOICES -from dcim.models import ( - Cable, ConsolePort, ConsoleServerPort, Device, DeviceBay, DeviceType, DeviceRole, FrontPort, FrontPortTemplate, - Interface, Manufacturer, Platform, PowerFeed, PowerOutlet, PowerPanel, PowerPort, PowerPortTemplate, Rack, - RackGroup, RackRole, RearPort, RearPortTemplate, Region, Site, VirtualChassis, -) +from dcim import models from utilities.api import ChoiceField, WritableNestedSerializer __all__ = [ 'NestedCableSerializer', 'NestedConsolePortSerializer', + 'NestedConsolePortTemplateSerializer', 'NestedConsoleServerPortSerializer', + 'NestedConsoleServerPortTemplateSerializer', 'NestedDeviceBaySerializer', + 'NestedDeviceBayTemplateSerializer', 'NestedDeviceRoleSerializer', 'NestedDeviceSerializer', 'NestedDeviceTypeSerializer', 'NestedFrontPortSerializer', 'NestedFrontPortTemplateSerializer', 'NestedInterfaceSerializer', + 'NestedInterfaceTemplateSerializer', + 'NestedInventoryItemSerializer', 'NestedManufacturerSerializer', 'NestedPlatformSerializer', 'NestedPowerFeedSerializer', 'NestedPowerOutletSerializer', + 'NestedPowerOutletTemplateSerializer', 'NestedPowerPanelSerializer', 'NestedPowerPortSerializer', 'NestedPowerPortTemplateSerializer', 'NestedRackGroupSerializer', + 'NestedRackReservationSerializer', 'NestedRackRoleSerializer', 'NestedRackSerializer', 'NestedRearPortSerializer', @@ -46,7 +49,7 @@ class NestedRegionSerializer(WritableNestedSerializer): site_count = serializers.IntegerField(read_only=True) class Meta: - model = Region + model = models.Region fields = ['id', 'url', 'name', 'slug', 'site_count'] @@ -54,7 +57,7 @@ class NestedSiteSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:site-detail') class Meta: - model = Site + model = models.Site fields = ['id', 'url', 'name', 'slug'] @@ -67,7 +70,7 @@ class NestedRackGroupSerializer(WritableNestedSerializer): rack_count = serializers.IntegerField(read_only=True) class Meta: - model = RackGroup + model = models.RackGroup fields = ['id', 'url', 'name', 'slug', 'rack_count'] @@ -76,7 +79,7 @@ class NestedRackRoleSerializer(WritableNestedSerializer): rack_count = serializers.IntegerField(read_only=True) class Meta: - model = RackRole + model = models.RackRole fields = ['id', 'url', 'name', 'slug', 'rack_count'] @@ -85,10 +88,22 @@ class NestedRackSerializer(WritableNestedSerializer): device_count = serializers.IntegerField(read_only=True) class Meta: - model = Rack + model = models.Rack fields = ['id', 'url', 'name', 'display_name', 'device_count'] +class NestedRackReservationSerializer(WritableNestedSerializer): + url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rackreservation-detail') + user = serializers.SerializerMethodField(read_only=True) + + class Meta: + model = models.RackReservation + fields = ['id', 'url', 'user', 'units'] + + def get_user(self, obj): + return obj.user.username + + # # Device types # @@ -98,7 +113,7 @@ class NestedManufacturerSerializer(WritableNestedSerializer): devicetype_count = serializers.IntegerField(read_only=True) class Meta: - model = Manufacturer + model = models.Manufacturer fields = ['id', 'url', 'name', 'slug', 'devicetype_count'] @@ -108,15 +123,47 @@ class NestedDeviceTypeSerializer(WritableNestedSerializer): device_count = serializers.IntegerField(read_only=True) class Meta: - model = DeviceType + model = models.DeviceType fields = ['id', 'url', 'manufacturer', 'model', 'slug', 'display_name', 'device_count'] +class NestedConsolePortTemplateSerializer(WritableNestedSerializer): + url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleporttemplate-detail') + + class Meta: + model = models.ConsolePortTemplate + fields = ['id', 'url', 'name'] + + +class NestedConsoleServerPortTemplateSerializer(WritableNestedSerializer): + url = serializers.HyperlinkedIdentityField(view_name='dcim-api:consoleserverporttemplate-detail') + + class Meta: + model = models.ConsoleServerPortTemplate + fields = ['id', 'url', 'name'] + + class NestedPowerPortTemplateSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerporttemplate-detail') class Meta: - model = PowerPortTemplate + model = models.PowerPortTemplate + fields = ['id', 'url', 'name'] + + +class NestedPowerOutletTemplateSerializer(WritableNestedSerializer): + url = serializers.HyperlinkedIdentityField(view_name='dcim-api:poweroutlettemplate-detail') + + class Meta: + model = models.PowerOutletTemplate + fields = ['id', 'url', 'name'] + + +class NestedInterfaceTemplateSerializer(WritableNestedSerializer): + url = serializers.HyperlinkedIdentityField(view_name='dcim-api:interfacetemplate-detail') + + class Meta: + model = models.InterfaceTemplate fields = ['id', 'url', 'name'] @@ -124,7 +171,7 @@ class NestedRearPortTemplateSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rearporttemplate-detail') class Meta: - model = RearPortTemplate + model = models.RearPortTemplate fields = ['id', 'url', 'name'] @@ -132,7 +179,15 @@ class NestedFrontPortTemplateSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:frontporttemplate-detail') class Meta: - model = FrontPortTemplate + model = models.FrontPortTemplate + fields = ['id', 'url', 'name'] + + +class NestedDeviceBayTemplateSerializer(WritableNestedSerializer): + url = serializers.HyperlinkedIdentityField(view_name='dcim-api:devicebaytemplate-detail') + + class Meta: + model = models.DeviceBayTemplate fields = ['id', 'url', 'name'] @@ -146,7 +201,7 @@ class NestedDeviceRoleSerializer(WritableNestedSerializer): virtualmachine_count = serializers.IntegerField(read_only=True) class Meta: - model = DeviceRole + model = models.DeviceRole fields = ['id', 'url', 'name', 'slug', 'device_count', 'virtualmachine_count'] @@ -156,7 +211,7 @@ class NestedPlatformSerializer(WritableNestedSerializer): virtualmachine_count = serializers.IntegerField(read_only=True) class Meta: - model = Platform + model = models.Platform fields = ['id', 'url', 'name', 'slug', 'device_count', 'virtualmachine_count'] @@ -164,7 +219,7 @@ class NestedDeviceSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:device-detail') class Meta: - model = Device + model = models.Device fields = ['id', 'url', 'name', 'display_name'] @@ -174,7 +229,7 @@ class NestedConsoleServerPortSerializer(WritableNestedSerializer): connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True) class Meta: - model = ConsoleServerPort + model = models.ConsoleServerPort fields = ['id', 'url', 'device', 'name', 'cable', 'connection_status'] @@ -184,7 +239,7 @@ class NestedConsolePortSerializer(WritableNestedSerializer): connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True) class Meta: - model = ConsolePort + model = models.ConsolePort fields = ['id', 'url', 'device', 'name', 'cable', 'connection_status'] @@ -194,7 +249,7 @@ class NestedPowerOutletSerializer(WritableNestedSerializer): connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True) class Meta: - model = PowerOutlet + model = models.PowerOutlet fields = ['id', 'url', 'device', 'name', 'cable', 'connection_status'] @@ -204,7 +259,7 @@ class NestedPowerPortSerializer(WritableNestedSerializer): connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True) class Meta: - model = PowerPort + model = models.PowerPort fields = ['id', 'url', 'device', 'name', 'cable', 'connection_status'] @@ -214,7 +269,7 @@ class NestedInterfaceSerializer(WritableNestedSerializer): connection_status = ChoiceField(choices=CONNECTION_STATUS_CHOICES, read_only=True) class Meta: - model = Interface + model = models.Interface fields = ['id', 'url', 'device', 'name', 'cable', 'connection_status'] @@ -223,7 +278,7 @@ class NestedRearPortSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rearport-detail') class Meta: - model = RearPort + model = models.RearPort fields = ['id', 'url', 'device', 'name', 'cable'] @@ -232,7 +287,7 @@ class NestedFrontPortSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:frontport-detail') class Meta: - model = FrontPort + model = models.FrontPort fields = ['id', 'url', 'device', 'name', 'cable'] @@ -241,7 +296,15 @@ class NestedDeviceBaySerializer(WritableNestedSerializer): device = NestedDeviceSerializer(read_only=True) class Meta: - model = DeviceBay + model = models.DeviceBay + fields = ['id', 'url', 'device', 'name'] + + +class NestedInventoryItemSerializer(WritableNestedSerializer): + url = serializers.HyperlinkedIdentityField(view_name='dcim-api:inventoryitem-detail') + + class Meta: + model = models.InventoryItem fields = ['id', 'url', 'device', 'name'] @@ -253,7 +316,7 @@ class NestedCableSerializer(serializers.ModelSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:cable-detail') class Meta: - model = Cable + model = models.Cable fields = ['id', 'url', 'label'] @@ -267,7 +330,7 @@ class NestedVirtualChassisSerializer(WritableNestedSerializer): member_count = serializers.IntegerField(read_only=True) class Meta: - model = VirtualChassis + model = models.VirtualChassis fields = ['id', 'url', 'master', 'member_count'] @@ -280,7 +343,7 @@ class NestedPowerPanelSerializer(WritableNestedSerializer): powerfeed_count = serializers.IntegerField(read_only=True) class Meta: - model = PowerPanel + model = models.PowerPanel fields = ['id', 'url', 'name', 'powerfeed_count'] @@ -288,5 +351,5 @@ class NestedPowerFeedSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerfeed-detail') class Meta: - model = PowerFeed + model = models.PowerFeed fields = ['id', 'url', 'name'] diff --git a/netbox/extras/api/nested_serializers.py b/netbox/extras/api/nested_serializers.py index 11367aba9..672b10a78 100644 --- a/netbox/extras/api/nested_serializers.py +++ b/netbox/extras/api/nested_serializers.py @@ -1,15 +1,49 @@ from rest_framework import serializers -from extras.models import ReportResult +from extras import models +from utilities.api import WritableNestedSerializer __all__ = [ + 'NestedConfigContextSerializer', + 'NestedExportTemplateSerializer', + 'NestedGraphSerializer', 'NestedReportResultSerializer', + 'NestedTagSerializer', ] -# -# Reports -# +class NestedConfigContextSerializer(WritableNestedSerializer): + url = serializers.HyperlinkedIdentityField(view_name='extras-api:configcontext-detail') + + class Meta: + model = models.ConfigContext + fields = ['id', 'url', 'name'] + + +class NestedExportTemplateSerializer(WritableNestedSerializer): + url = serializers.HyperlinkedIdentityField(view_name='extras-api:exporttemplate-detail') + + class Meta: + model = models.ExportTemplate + fields = ['id', 'url', 'name'] + + +class NestedGraphSerializer(WritableNestedSerializer): + url = serializers.HyperlinkedIdentityField(view_name='extras-api:graph-detail') + + class Meta: + model = models.Graph + fields = ['id', 'url', 'name'] + + +class NestedTagSerializer(WritableNestedSerializer): + url = serializers.HyperlinkedIdentityField(view_name='extras-api:tag-detail') + tagged_items = serializers.IntegerField(read_only=True) + + class Meta: + model = models.Tag + fields = ['id', 'url', 'name', 'slug', 'color', 'tagged_items'] + class NestedReportResultSerializer(serializers.ModelSerializer): url = serializers.HyperlinkedIdentityField( @@ -19,5 +53,5 @@ class NestedReportResultSerializer(serializers.ModelSerializer): ) class Meta: - model = ReportResult + model = models.ReportResult fields = ['url', 'created', 'user', 'failed'] diff --git a/netbox/ipam/api/nested_serializers.py b/netbox/ipam/api/nested_serializers.py index aa7c95f1c..abe75b261 100644 --- a/netbox/ipam/api/nested_serializers.py +++ b/netbox/ipam/api/nested_serializers.py @@ -1,6 +1,6 @@ from rest_framework import serializers -from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, VLAN, VLANGroup, VRF +from ipam import models from utilities.api import WritableNestedSerializer __all__ = [ @@ -9,6 +9,7 @@ __all__ = [ 'NestedPrefixSerializer', 'NestedRIRSerializer', 'NestedRoleSerializer', + 'NestedServiceSerializer', 'NestedVLANGroupSerializer', 'NestedVLANSerializer', 'NestedVRFSerializer', @@ -24,7 +25,7 @@ class NestedVRFSerializer(WritableNestedSerializer): prefix_count = serializers.IntegerField(read_only=True) class Meta: - model = VRF + model = models.VRF fields = ['id', 'url', 'name', 'rd', 'prefix_count'] @@ -37,7 +38,7 @@ class NestedRIRSerializer(WritableNestedSerializer): aggregate_count = serializers.IntegerField(read_only=True) class Meta: - model = RIR + model = models.RIR fields = ['id', 'url', 'name', 'slug', 'aggregate_count'] @@ -45,7 +46,7 @@ class NestedAggregateSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='ipam-api:aggregate-detail') class Meta: - model = Aggregate + model = models.Aggregate fields = ['id', 'url', 'family', 'prefix'] @@ -59,7 +60,7 @@ class NestedRoleSerializer(WritableNestedSerializer): vlan_count = serializers.IntegerField(read_only=True) class Meta: - model = Role + model = models.Role fields = ['id', 'url', 'name', 'slug', 'prefix_count', 'vlan_count'] @@ -68,7 +69,7 @@ class NestedVLANGroupSerializer(WritableNestedSerializer): vlan_count = serializers.IntegerField(read_only=True) class Meta: - model = VLANGroup + model = models.VLANGroup fields = ['id', 'url', 'name', 'slug', 'vlan_count'] @@ -76,7 +77,7 @@ class NestedVLANSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vlan-detail') class Meta: - model = VLAN + model = models.VLAN fields = ['id', 'url', 'vid', 'name', 'display_name'] @@ -88,7 +89,7 @@ class NestedPrefixSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='ipam-api:prefix-detail') class Meta: - model = Prefix + model = models.Prefix fields = ['id', 'url', 'family', 'prefix'] @@ -96,10 +97,21 @@ class NestedPrefixSerializer(WritableNestedSerializer): # IP addresses # - class NestedIPAddressSerializer(WritableNestedSerializer): url = serializers.HyperlinkedIdentityField(view_name='ipam-api:ipaddress-detail') class Meta: - model = IPAddress + model = models.IPAddress fields = ['id', 'url', 'family', 'address'] + + +# +# Services +# + +class NestedServiceSerializer(WritableNestedSerializer): + url = serializers.HyperlinkedIdentityField(view_name='ipam-api:service-detail') + + class Meta: + model = models.Service + fields = ['id', 'url', 'name', 'protocol', 'port']