diff --git a/netbox/circuits/api/serializers.py b/netbox/circuits/api/serializers.py index 4f88b9b28..54c6943ea 100644 --- a/netbox/circuits/api/serializers.py +++ b/netbox/circuits/api/serializers.py @@ -40,6 +40,7 @@ class ProviderSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'accounts', 'description', 'comments', 'asns', 'tags', 'custom_fields', 'created', 'last_updated', 'circuit_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'circuit_count') # @@ -56,6 +57,7 @@ class ProviderAccountSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'provider', 'name', 'account', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name', 'account') # @@ -72,6 +74,7 @@ class ProviderNetworkSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'provider', 'name', 'service_id', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') # @@ -90,6 +93,7 @@ class CircuitTypeSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'color', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'circuit_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'circuit_count') class CircuitCircuitTerminationSerializer(WritableNestedSerializer): @@ -122,6 +126,7 @@ class CircuitSerializer(NetBoxModelSerializer): 'termination_date', 'commit_rate', 'description', 'termination_a', 'termination_z', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'cid') class CircuitTerminationSerializer(NetBoxModelSerializer, CabledObjectSerializer): @@ -137,3 +142,4 @@ class CircuitTerminationSerializer(NetBoxModelSerializer, CabledObjectSerializer 'xconnect_id', 'pp_info', 'description', 'mark_connected', 'cable', 'cable_end', 'link_peers', 'link_peers_type', 'tags', 'custom_fields', 'created', 'last_updated', '_occupied', ] + brief_fields = ('id', 'url', 'display', 'circuit', 'term_side', 'cable', '_occupied') diff --git a/netbox/core/api/serializers.py b/netbox/core/api/serializers.py index d685ba43d..86417dda1 100644 --- a/netbox/core/api/serializers.py +++ b/netbox/core/api/serializers.py @@ -36,6 +36,7 @@ class DataSourceSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'type', 'source_url', 'enabled', 'status', 'description', 'comments', 'parameters', 'ignore_rules', 'custom_fields', 'created', 'last_updated', 'file_count', ] + brief_fields = ('id', 'url', 'display', 'name') class DataFileSerializer(NetBoxModelSerializer): @@ -51,6 +52,7 @@ class DataFileSerializer(NetBoxModelSerializer): fields = [ 'id', 'url', 'display', 'source', 'path', 'last_updated', 'size', 'hash', ] + brief_fields = ('id', 'url', 'display', 'path') class JobSerializer(BaseModelSerializer): @@ -69,3 +71,4 @@ class JobSerializer(BaseModelSerializer): 'id', 'url', 'display', 'object_type', 'object_id', 'name', 'status', 'created', 'scheduled', 'interval', 'started', 'completed', 'user', 'data', 'error', 'job_id', ] + brief_fields = ('url', 'created', 'completed', 'user', 'status') diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py index 7f18ebc2b..c1237b835 100644 --- a/netbox/dcim/api/serializers.py +++ b/netbox/dcim/api/serializers.py @@ -114,6 +114,7 @@ class RegionSerializer(NestedGroupModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'parent', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'site_count', '_depth', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'site_count', '_depth') class SiteGroupSerializer(NestedGroupModelSerializer): @@ -127,6 +128,7 @@ class SiteGroupSerializer(NestedGroupModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'parent', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'site_count', '_depth', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'site_count', '_depth') class SiteSerializer(NetBoxModelSerializer): @@ -159,6 +161,7 @@ class SiteSerializer(NetBoxModelSerializer): 'custom_fields', 'created', 'last_updated', 'circuit_count', 'device_count', 'prefix_count', 'rack_count', 'virtualmachine_count', 'vlan_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug') # @@ -180,6 +183,7 @@ class LocationSerializer(NestedGroupModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'site', 'parent', 'status', 'tenant', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'rack_count', 'device_count', '_depth', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'rack_count', '_depth') class RackRoleSerializer(NetBoxModelSerializer): @@ -194,6 +198,7 @@ class RackRoleSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'color', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'rack_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'rack_count') class RackSerializer(NetBoxModelSerializer): @@ -222,6 +227,7 @@ class RackSerializer(NetBoxModelSerializer): 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', 'mounting_depth', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'device_count', 'powerfeed_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'device_count') class RackUnitSerializer(serializers.Serializer): @@ -256,6 +262,7 @@ class RackReservationSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'rack', 'units', 'created', 'last_updated', 'user', 'tenant', 'description', 'comments', 'tags', 'custom_fields', ] + brief_fields = ('id', 'url', 'display', 'user', 'units') class RackElevationDetailFilterSerializer(serializers.Serializer): @@ -315,6 +322,7 @@ class ManufacturerSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'devicetype_count', 'inventoryitem_count', 'platform_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'devicetype_count') class DeviceTypeSerializer(NetBoxModelSerializer): @@ -360,6 +368,7 @@ class DeviceTypeSerializer(NetBoxModelSerializer): 'rear_port_template_count', 'device_bay_template_count', 'module_bay_template_count', 'inventory_item_template_count', ] + brief_fields = ('id', 'url', 'display', 'manufacturer', 'model', 'slug', 'device_count') class ModuleTypeSerializer(NetBoxModelSerializer): @@ -373,6 +382,7 @@ class ModuleTypeSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'manufacturer', 'model', 'part_number', 'weight', 'weight_unit', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'manufacturer', 'model') # @@ -403,6 +413,7 @@ class ConsolePortTemplateSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'device_type', 'module_type', 'name', 'label', 'type', 'description', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') class ConsoleServerPortTemplateSerializer(ValidatedModelSerializer): @@ -429,6 +440,7 @@ class ConsoleServerPortTemplateSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'device_type', 'module_type', 'name', 'label', 'type', 'description', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') class PowerPortTemplateSerializer(ValidatedModelSerializer): @@ -456,6 +468,7 @@ class PowerPortTemplateSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'device_type', 'module_type', 'name', 'label', 'type', 'maximum_draw', 'allocated_draw', 'description', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') class PowerOutletTemplateSerializer(ValidatedModelSerializer): @@ -493,6 +506,7 @@ class PowerOutletTemplateSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'device_type', 'module_type', 'name', 'label', 'type', 'power_port', 'feed_leg', 'description', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') class InterfaceTemplateSerializer(ValidatedModelSerializer): @@ -537,6 +551,7 @@ class InterfaceTemplateSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'device_type', 'module_type', 'name', 'label', 'type', 'enabled', 'mgmt_only', 'description', 'bridge', 'poe_mode', 'poe_type', 'rf_role', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') class RearPortTemplateSerializer(ValidatedModelSerializer): @@ -559,6 +574,7 @@ class RearPortTemplateSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'device_type', 'module_type', 'name', 'label', 'type', 'color', 'positions', 'description', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') class FrontPortTemplateSerializer(ValidatedModelSerializer): @@ -582,6 +598,7 @@ class FrontPortTemplateSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'device_type', 'module_type', 'name', 'label', 'type', 'color', 'rear_port', 'rear_port_position', 'description', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') class ModuleBayTemplateSerializer(ValidatedModelSerializer): @@ -594,6 +611,7 @@ class ModuleBayTemplateSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'device_type', 'name', 'label', 'position', 'description', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') class DeviceBayTemplateSerializer(ValidatedModelSerializer): @@ -603,6 +621,7 @@ class DeviceBayTemplateSerializer(ValidatedModelSerializer): class Meta: model = DeviceBayTemplate fields = ['id', 'url', 'display', 'device_type', 'name', 'label', 'description', 'created', 'last_updated'] + brief_fields = ('id', 'url', 'display', 'name') class InventoryItemTemplateSerializer(ValidatedModelSerializer): @@ -629,6 +648,7 @@ class InventoryItemTemplateSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'device_type', 'parent', 'name', 'label', 'role', 'manufacturer', 'part_id', 'description', 'component_type', 'component_id', 'component', 'created', 'last_updated', '_depth', ] + brief_fields = ('id', 'url', 'display', 'name', '_depth') @extend_schema_field(serializers.JSONField(allow_null=True)) def get_component(self, obj): @@ -657,6 +677,7 @@ class DeviceRoleSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'color', 'vm_role', 'config_template', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'device_count', 'virtualmachine_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'device_count', 'virtualmachine_count') class PlatformSerializer(NetBoxModelSerializer): @@ -674,6 +695,7 @@ class PlatformSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'manufacturer', 'config_template', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'device_count', 'virtualmachine_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'device_count', 'virtualmachine_count') class DeviceSerializer(NetBoxModelSerializer): @@ -730,6 +752,7 @@ class DeviceSerializer(NetBoxModelSerializer): 'power_port_count', 'power_outlet_count', 'interface_count', 'front_port_count', 'rear_port_count', 'device_bay_count', 'module_bay_count', 'inventory_item_count', ] + brief_fields = ('id', 'url', 'display', 'name') @extend_schema_field(NestedDeviceSerializer) def get_parent_device(self, obj): @@ -784,6 +807,7 @@ class VirtualDeviceContextSerializer(NetBoxModelSerializer): 'primary_ip6', 'status', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'interface_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'identifier', 'device') class ModuleSerializer(NetBoxModelSerializer): @@ -799,6 +823,7 @@ class ModuleSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'device', 'module_bay', 'module_type', 'status', 'serial', 'asset_tag', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'device', 'module_bay', 'module_type') # @@ -831,6 +856,7 @@ class ConsoleServerPortSerializer(NetBoxModelSerializer, CabledObjectSerializer, 'connected_endpoints_type', 'connected_endpoints_reachable', 'tags', 'custom_fields', 'created', 'last_updated', '_occupied', ] + brief_fields = ('id', 'url', 'display', 'device', 'name', 'cable', '_occupied') class ConsolePortSerializer(NetBoxModelSerializer, CabledObjectSerializer, ConnectedEndpointsSerializer): @@ -859,6 +885,7 @@ class ConsolePortSerializer(NetBoxModelSerializer, CabledObjectSerializer, Conne 'connected_endpoints_type', 'connected_endpoints_reachable', 'tags', 'custom_fields', 'created', 'last_updated', '_occupied', ] + brief_fields = ('id', 'url', 'display', 'device', 'name', 'cable', '_occupied') class PowerOutletSerializer(NetBoxModelSerializer, CabledObjectSerializer, ConnectedEndpointsSerializer): @@ -893,6 +920,7 @@ class PowerOutletSerializer(NetBoxModelSerializer, CabledObjectSerializer, Conne 'connected_endpoints', 'connected_endpoints_type', 'connected_endpoints_reachable', 'tags', 'custom_fields', 'created', 'last_updated', '_occupied', ] + brief_fields = ('id', 'url', 'display', 'device', 'name', 'cable', '_occupied') class PowerPortSerializer(NetBoxModelSerializer, CabledObjectSerializer, ConnectedEndpointsSerializer): @@ -917,6 +945,7 @@ class PowerPortSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect 'connected_endpoints', 'connected_endpoints_type', 'connected_endpoints_reachable', 'tags', 'custom_fields', 'created', 'last_updated', '_occupied', ] + brief_fields = ('id', 'url', 'display', 'device', 'name', 'cable', '_occupied') class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, ConnectedEndpointsSerializer): @@ -979,6 +1008,7 @@ class InterfaceSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect 'connected_endpoints_type', 'connected_endpoints_reachable', 'tags', 'custom_fields', 'created', 'last_updated', 'count_ipaddresses', 'count_fhrp_groups', '_occupied', ] + brief_fields = ('id', 'url', 'display', 'device', 'name', 'cable', '_occupied') def validate(self, data): @@ -1010,6 +1040,7 @@ class RearPortSerializer(NetBoxModelSerializer, CabledObjectSerializer): 'mark_connected', 'cable', 'cable_end', 'link_peers', 'link_peers_type', 'tags', 'custom_fields', 'created', 'last_updated', '_occupied', ] + brief_fields = ('id', 'url', 'display', 'device', 'name', 'cable', '_occupied') class FrontPortRearPortSerializer(WritableNestedSerializer): @@ -1040,6 +1071,7 @@ class FrontPortSerializer(NetBoxModelSerializer, CabledObjectSerializer): 'rear_port_position', 'description', 'mark_connected', 'cable', 'cable_end', 'link_peers', 'link_peers_type', 'tags', 'custom_fields', 'created', 'last_updated', '_occupied', ] + brief_fields = ('id', 'url', 'display', 'device', 'name', 'cable', '_occupied') class ModuleBaySerializer(NetBoxModelSerializer): @@ -1051,9 +1083,9 @@ class ModuleBaySerializer(NetBoxModelSerializer): model = ModuleBay fields = [ 'id', 'url', 'display', 'device', 'name', 'installed_module', 'label', 'position', 'description', 'tags', - 'custom_fields', - 'created', 'last_updated', + 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'installed_module', 'name') class DeviceBaySerializer(NetBoxModelSerializer): @@ -1067,6 +1099,7 @@ class DeviceBaySerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'device', 'name', 'label', 'description', 'installed_device', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'device', 'name') class InventoryItemSerializer(NetBoxModelSerializer): @@ -1090,6 +1123,7 @@ class InventoryItemSerializer(NetBoxModelSerializer): 'asset_tag', 'discovered', 'description', 'component_type', 'component_id', 'component', 'tags', 'custom_fields', 'created', 'last_updated', '_depth', ] + brief_fields = ('id', 'url', 'display', 'device', 'name', '_depth') @extend_schema_field(serializers.JSONField(allow_null=True)) def get_component(self, obj): @@ -1116,6 +1150,7 @@ class InventoryItemRoleSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'color', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'inventoryitem_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'inventoryitem_count') # @@ -1136,6 +1171,7 @@ class CableSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'type', 'a_terminations', 'b_terminations', 'status', 'tenant', 'label', 'color', 'length', 'length_unit', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'label') class TracedCableSerializer(serializers.ModelSerializer): @@ -1206,6 +1242,7 @@ class VirtualChassisSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'domain', 'master', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'member_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'master', 'member_count') # @@ -1230,6 +1267,7 @@ class PowerPanelSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'site', 'location', 'name', 'description', 'comments', 'tags', 'custom_fields', 'powerfeed_count', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name', 'powerfeed_count') class PowerFeedSerializer(NetBoxModelSerializer, CabledObjectSerializer, ConnectedEndpointsSerializer): @@ -1269,3 +1307,4 @@ class PowerFeedSerializer(NetBoxModelSerializer, CabledObjectSerializer, Connect 'connected_endpoints', 'connected_endpoints_type', 'connected_endpoints_reachable', 'description', 'tenant', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', '_occupied', ] + brief_fields = ('id', 'url', 'display', 'name', 'cable', '_occupied') diff --git a/netbox/dcim/tests/test_api.py b/netbox/dcim/tests/test_api.py index f17f4a03f..ef085e7ec 100644 --- a/netbox/dcim/tests/test_api.py +++ b/netbox/dcim/tests/test_api.py @@ -1755,7 +1755,7 @@ class RearPortTest(APIViewTestCases.APIViewTestCase): class ModuleBayTest(APIViewTestCases.APIViewTestCase): model = ModuleBay - brief_fields = ['display', 'id', 'module', 'name', 'url'] + brief_fields = ['display', 'id', 'installed_module', 'name', 'url'] bulk_update_data = { 'description': 'New description', } diff --git a/netbox/extras/api/serializers.py b/netbox/extras/api/serializers.py index 7058bb276..0b8138d4e 100644 --- a/netbox/extras/api/serializers.py +++ b/netbox/extras/api/serializers.py @@ -76,6 +76,7 @@ class EventRuleSerializer(NetBoxModelSerializer): 'type_job_start', 'type_job_end', 'enabled', 'conditions', 'action_type', 'action_object_type', 'action_object_id', 'action_object', 'description', 'custom_fields', 'tags', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') @extend_schema_field(OpenApiTypes.OBJECT) def get_action_object(self, instance): @@ -107,6 +108,7 @@ class WebhookSerializer(NetBoxModelSerializer): 'additional_headers', 'body_template', 'secret', 'ssl_verification', 'ca_file_path', 'custom_fields', 'tags', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') # @@ -142,6 +144,7 @@ class CustomFieldSerializer(ValidatedModelSerializer): 'default', 'weight', 'validation_minimum', 'validation_maximum', 'validation_regex', 'choice_set', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') def validate_type(self, value): if self.instance and self.instance.type != value: @@ -184,6 +187,7 @@ class CustomFieldChoiceSetSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'name', 'description', 'base_choices', 'extra_choices', 'order_alphabetically', 'choices_count', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name', 'choices_count') # @@ -203,6 +207,7 @@ class CustomLinkSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'content_types', 'name', 'enabled', 'link_text', 'link_url', 'weight', 'group_name', 'button_class', 'new_window', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') # @@ -229,6 +234,7 @@ class ExportTemplateSerializer(ValidatedModelSerializer): 'file_extension', 'as_attachment', 'data_source', 'data_path', 'data_file', 'data_synced', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') # @@ -248,6 +254,7 @@ class SavedFilterSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'content_types', 'name', 'slug', 'description', 'user', 'weight', 'enabled', 'shared', 'parameters', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug') # @@ -267,6 +274,7 @@ class BookmarkSerializer(ValidatedModelSerializer): fields = [ 'id', 'url', 'display', 'object_type', 'object_id', 'object', 'user', 'created', ] + brief_fields = ('id', 'url', 'display', 'object_id', 'object_type') @extend_schema_field(serializers.JSONField(allow_null=True)) def get_object(self, instance): @@ -295,6 +303,7 @@ class TagSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'color', 'description', 'object_types', 'tagged_items', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'color') # @@ -314,6 +323,7 @@ class ImageAttachmentSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'content_type', 'object_id', 'parent', 'name', 'image', 'image_height', 'image_width', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name', 'image') def validate(self, data): @@ -363,6 +373,7 @@ class JournalEntrySerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'assigned_object_type', 'assigned_object_id', 'assigned_object', 'created', 'created_by', 'kind', 'comments', 'tags', 'custom_fields', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'created') def validate(self, data): @@ -486,6 +497,7 @@ class ConfigContextSerializer(ValidatedModelSerializer): 'tenant_groups', 'tenants', 'tags', 'data_source', 'data_path', 'data_file', 'data_synced', 'data', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') # @@ -507,6 +519,7 @@ class ConfigTemplateSerializer(TaggableModelSerializer, ValidatedModelSerializer 'id', 'url', 'display', 'name', 'description', 'environment_params', 'template_code', 'data_source', 'data_path', 'data_file', 'data_synced', 'tags', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') # @@ -524,6 +537,7 @@ class ScriptSerializer(ValidatedModelSerializer): fields = [ 'id', 'url', 'module', 'name', 'description', 'vars', 'result', 'display', 'is_executable', ] + brief_fields = ('id', 'url', 'display', 'name') @extend_schema_field(serializers.JSONField(allow_null=True)) def get_vars(self, obj): diff --git a/netbox/ipam/api/serializers.py b/netbox/ipam/api/serializers.py index eedb19915..a62c92f49 100644 --- a/netbox/ipam/api/serializers.py +++ b/netbox/ipam/api/serializers.py @@ -33,6 +33,7 @@ class ASNRangeSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'rir', 'start', 'end', 'tenant', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'asn_count', ] + brief_fields = ('id', 'url', 'display', 'name') # @@ -54,6 +55,7 @@ class ASNSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'asn', 'rir', 'tenant', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'site_count', 'provider_count', ] + brief_fields = ('id', 'url', 'display', 'asn') class AvailableASNSerializer(serializers.Serializer): @@ -104,6 +106,7 @@ class VRFSerializer(NetBoxModelSerializer): 'import_targets', 'export_targets', 'tags', 'custom_fields', 'created', 'last_updated', 'ipaddress_count', 'prefix_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'rd', 'prefix_count') # @@ -120,6 +123,7 @@ class RouteTargetSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'tenant', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') # @@ -138,6 +142,7 @@ class RIRSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'is_private', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'aggregate_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'aggregate_count') class AggregateSerializer(NetBoxModelSerializer): @@ -153,6 +158,7 @@ class AggregateSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'family', 'prefix', 'rir', 'tenant', 'date_added', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'family', 'prefix') # @@ -169,6 +175,7 @@ class FHRPGroupSerializer(NetBoxModelSerializer): 'id', 'name', 'url', 'display', 'protocol', 'group_id', 'auth_type', 'auth_key', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'ip_addresses', ] + brief_fields = ('id', 'url', 'display', 'protocol', 'group_id') class FHRPGroupAssignmentSerializer(NetBoxModelSerializer): @@ -185,6 +192,7 @@ class FHRPGroupAssignmentSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'group', 'interface_type', 'interface_id', 'interface', 'priority', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'group', 'interface_type', 'interface_id', 'priority') @extend_schema_field(serializers.JSONField(allow_null=True)) def get_interface(self, obj): @@ -212,6 +220,7 @@ class RoleSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'weight', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'prefix_count', 'vlan_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'prefix_count', 'vlan_count') class VLANGroupSerializer(NetBoxModelSerializer): @@ -237,6 +246,7 @@ class VLANGroupSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'scope_type', 'scope_id', 'scope', 'min_vid', 'max_vid', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'vlan_count', 'utilization' ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'vlan_count') validators = [] @extend_schema_field(serializers.JSONField(allow_null=True)) @@ -267,6 +277,7 @@ class VLANSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description', 'comments', 'l2vpn_termination', 'tags', 'custom_fields', 'created', 'last_updated', 'prefix_count', ] + brief_fields = ('id', 'url', 'display', 'vid', 'name') class AvailableVLANSerializer(serializers.Serializer): @@ -327,6 +338,7 @@ class PrefixSerializer(NetBoxModelSerializer): 'mark_utilized', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'children', '_depth', ] + brief_fields = ('id', 'url', 'display', 'family', 'prefix', '_depth') class PrefixLengthSerializer(serializers.Serializer): @@ -397,6 +409,7 @@ class IPRangeSerializer(NetBoxModelSerializer): 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'mark_utilized', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'family', 'start_address', 'end_address') # @@ -427,6 +440,7 @@ class IPAddressSerializer(NetBoxModelSerializer): 'assigned_object_id', 'assigned_object', 'nat_inside', 'nat_outside', 'dns_name', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'family', 'address') @extend_schema_field(serializers.JSONField(allow_null=True)) def get_assigned_object(self, obj): @@ -472,6 +486,7 @@ class ServiceTemplateSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'ports', 'protocol', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name', 'protocol', 'ports') class ServiceSerializer(NetBoxModelSerializer): @@ -492,3 +507,4 @@ class ServiceSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'device', 'virtual_machine', 'name', 'ports', 'protocol', 'ipaddresses', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name', 'protocol', 'ports') diff --git a/netbox/netbox/api/viewsets/__init__.py b/netbox/netbox/api/viewsets/__init__.py index 2ff764bed..2f0431efa 100644 --- a/netbox/netbox/api/viewsets/__init__.py +++ b/netbox/netbox/api/viewsets/__init__.py @@ -34,6 +34,8 @@ class BaseViewSet(GenericViewSet): """ Base class for all API ViewSets. This is responsible for the enforcement of object-based permissions. """ + brief = False + def initial(self, request, *args, **kwargs): super().initial(request, *args, **kwargs) @@ -42,6 +44,13 @@ class BaseViewSet(GenericViewSet): if action := HTTP_ACTIONS[request.method]: self.queryset = self.queryset.restrict(request.user, action) + def initialize_request(self, request, *args, **kwargs): + + # Annotate whether brief mode is active + self.brief = request.method == 'GET' and request.GET.get('brief') + + return super().initialize_request(request, *args, **kwargs) + def get_queryset(self): qs = super().get_queryset() serializer_class = self.get_serializer_class() @@ -66,12 +75,17 @@ class BaseViewSet(GenericViewSet): @cached_property def requested_fields(self): - requested_fields = self.request.query_params.get('fields') - return requested_fields.split(',') if requested_fields else [] + # An explicit list of fields was requested + if requested_fields := self.request.query_params.get('fields'): + return requested_fields.split(',') + # Brief mode has been enabled for this request + elif self.brief: + serializer_class = self.get_serializer_class() + return getattr(serializer_class.Meta, 'brief_fields', None) + return None class NetBoxReadOnlyModelViewSet( - mixins.BriefModeMixin, mixins.CustomFieldsMixin, mixins.ExportTemplatesMixin, drf_mixins.RetrieveModelMixin, @@ -85,7 +99,6 @@ class NetBoxModelViewSet( mixins.BulkUpdateModelMixin, mixins.BulkDestroyModelMixin, mixins.ObjectValidationMixin, - mixins.BriefModeMixin, mixins.CustomFieldsMixin, mixins.ExportTemplatesMixin, drf_mixins.CreateModelMixin, diff --git a/netbox/netbox/api/viewsets/mixins.py b/netbox/netbox/api/viewsets/mixins.py index b2c6bdda6..9d8286968 100644 --- a/netbox/netbox/api/viewsets/mixins.py +++ b/netbox/netbox/api/viewsets/mixins.py @@ -1,5 +1,3 @@ -import logging - from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ObjectDoesNotExist from django.db import transaction @@ -8,13 +6,9 @@ from rest_framework import status from rest_framework.response import Response from extras.models import ExportTemplate -from netbox.api.exceptions import SerializerNotFound from netbox.api.serializers import BulkOperationSerializer -from netbox.constants import NESTED_SERIALIZER_PREFIX -from utilities.api import get_serializer_for_model __all__ = ( - 'BriefModeMixin', 'BulkDestroyModelMixin', 'BulkUpdateModelMixin', 'CustomFieldsMixin', @@ -24,35 +18,6 @@ __all__ = ( ) -class BriefModeMixin: - """ - Enables brief mode support, so that the client can invoke a model's nested serializer by passing e.g. - GET /api/dcim/sites/?brief=True - """ - brief = False - - def initialize_request(self, request, *args, **kwargs): - # Annotate whether brief mode is active - self.brief = request.method == 'GET' and request.GET.get('brief') - - return super().initialize_request(request, *args, **kwargs) - - def get_serializer_class(self): - logger = logging.getLogger(f'netbox.api.views.{self.__class__.__name__}') - - # If using 'brief' mode, find and return the nested serializer for this model, if one exists - if self.brief: - logger.debug("Request is for 'brief' format; initializing nested serializer") - try: - return get_serializer_for_model(self.queryset.model, prefix=NESTED_SERIALIZER_PREFIX) - except SerializerNotFound: - logger.debug( - f"Nested serializer for {self.queryset.model} not found! Using serializer {self.serializer_class}" - ) - - return self.serializer_class - - class CustomFieldsMixin: """ For models which support custom fields, populate the `custom_fields` context. diff --git a/netbox/tenancy/api/serializers.py b/netbox/tenancy/api/serializers.py index ce16f2523..304f57e8d 100644 --- a/netbox/tenancy/api/serializers.py +++ b/netbox/tenancy/api/serializers.py @@ -27,6 +27,7 @@ class TenantGroupSerializer(NestedGroupModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'parent', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'tenant_count', '_depth', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'tenant_count', '_depth') class TenantSerializer(NetBoxModelSerializer): @@ -52,6 +53,7 @@ class TenantSerializer(NetBoxModelSerializer): 'created', 'last_updated', 'circuit_count', 'device_count', 'ipaddress_count', 'prefix_count', 'rack_count', 'site_count', 'virtualmachine_count', 'vlan_count', 'vrf_count', 'cluster_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug') # @@ -69,6 +71,7 @@ class ContactGroupSerializer(NestedGroupModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'parent', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'contact_count', '_depth', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'contact_count', '_depth') class ContactRoleSerializer(NetBoxModelSerializer): @@ -79,6 +82,7 @@ class ContactRoleSerializer(NetBoxModelSerializer): fields = [ 'id', 'url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug') class ContactSerializer(NetBoxModelSerializer): @@ -91,6 +95,7 @@ class ContactSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'group', 'name', 'title', 'phone', 'email', 'address', 'link', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'name') class ContactAssignmentSerializer(NetBoxModelSerializer): @@ -109,6 +114,7 @@ class ContactAssignmentSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'content_type', 'object_id', 'object', 'contact', 'role', 'priority', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'contact', 'role', 'priority') @extend_schema_field(OpenApiTypes.OBJECT) def get_object(self, instance): diff --git a/netbox/users/api/serializers.py b/netbox/users/api/serializers.py index 0a397d06f..e398014b8 100644 --- a/netbox/users/api/serializers.py +++ b/netbox/users/api/serializers.py @@ -37,6 +37,7 @@ class UserSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'username', 'password', 'first_name', 'last_name', 'email', 'is_staff', 'is_active', 'date_joined', 'last_login', 'groups', ) + brief_fields = ('id', 'url', 'display', 'username') extra_kwargs = { 'password': {'write_only': True} } @@ -76,6 +77,7 @@ class GroupSerializer(ValidatedModelSerializer): class Meta: model = Group fields = ('id', 'url', 'display', 'name', 'user_count') + brief_fields = ('id', 'url', 'display', 'name') class TokenSerializer(ValidatedModelSerializer): @@ -101,6 +103,7 @@ class TokenSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'user', 'created', 'expires', 'last_used', 'key', 'write_enabled', 'description', 'allowed_ips', ) + brief_fields = ('id', 'url', 'display', 'key', 'write_enabled') def to_internal_value(self, data): if 'key' not in data: @@ -181,3 +184,4 @@ class ObjectPermissionSerializer(ValidatedModelSerializer): 'id', 'url', 'display', 'name', 'description', 'enabled', 'object_types', 'groups', 'users', 'actions', 'constraints', ) + brief_fields = ('id', 'url', 'display', 'name', 'enabled', 'object_types', 'groups', 'users', 'actions') diff --git a/netbox/virtualization/api/serializers.py b/netbox/virtualization/api/serializers.py index 650c3bcab..68b9c96f9 100644 --- a/netbox/virtualization/api/serializers.py +++ b/netbox/virtualization/api/serializers.py @@ -33,6 +33,7 @@ class ClusterTypeSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'cluster_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'cluster_count') class ClusterGroupSerializer(NetBoxModelSerializer): @@ -47,6 +48,7 @@ class ClusterGroupSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'cluster_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'cluster_count') class ClusterSerializer(NetBoxModelSerializer): @@ -67,6 +69,7 @@ class ClusterSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'type', 'group', 'status', 'tenant', 'site', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'device_count', 'virtualmachine_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'virtualmachine_count') # @@ -99,6 +102,7 @@ class VirtualMachineSerializer(NetBoxModelSerializer): 'config_template', 'local_context_data', 'tags', 'custom_fields', 'created', 'last_updated', 'interface_count', 'virtual_disk_count', ] + brief_fields = ('id', 'url', 'display', 'name') validators = [] @@ -152,6 +156,7 @@ class VMInterfaceSerializer(NetBoxModelSerializer): 'description', 'mode', 'untagged_vlan', 'tagged_vlans', 'vrf', 'l2vpn_termination', 'tags', 'custom_fields', 'created', 'last_updated', 'count_ipaddresses', 'count_fhrp_groups', ] + brief_fields = ('id', 'url', 'display', 'virtual_machine', 'name') def validate(self, data): @@ -178,6 +183,7 @@ class VirtualDiskSerializer(NetBoxModelSerializer): class Meta: model = VirtualDisk fields = [ - 'id', 'url', 'virtual_machine', 'name', 'description', 'size', 'tags', 'custom_fields', 'created', - 'last_updated', + 'id', 'url', 'display', 'virtual_machine', 'name', 'description', 'size', 'tags', 'custom_fields', + 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'virtual_machine', 'name', 'size') diff --git a/netbox/vpn/api/serializers.py b/netbox/vpn/api/serializers.py index 4e1bfef03..49c60b048 100644 --- a/netbox/vpn/api/serializers.py +++ b/netbox/vpn/api/serializers.py @@ -39,6 +39,7 @@ class TunnelGroupSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'tunnel_count', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'tunnel_count') class TunnelSerializer(NetBoxModelSerializer): @@ -73,6 +74,7 @@ class TunnelSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'status', 'group', 'encapsulation', 'ipsec_profile', 'tenant', 'tunnel_id', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'terminations_count', ) + brief_fields = ('id', 'url', 'display', 'name') class TunnelTerminationSerializer(NetBoxModelSerializer): @@ -100,6 +102,7 @@ class TunnelTerminationSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'tunnel', 'role', 'termination_type', 'termination_id', 'termination', 'outside_ip', 'tags', 'custom_fields', 'created', 'last_updated', ) + brief_fields = ('id', 'url', 'display') @extend_schema_field(serializers.JSONField(allow_null=True)) def get_termination(self, obj): @@ -132,6 +135,7 @@ class IKEProposalSerializer(NetBoxModelSerializer): 'authentication_algorithm', 'group', 'sa_lifetime', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ) + brief_fields = ('id', 'url', 'display', 'name') class IKEPolicySerializer(NetBoxModelSerializer): @@ -157,6 +161,7 @@ class IKEPolicySerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'description', 'version', 'mode', 'proposals', 'preshared_key', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ) + brief_fields = ('id', 'url', 'display', 'name') class IPSecProposalSerializer(NetBoxModelSerializer): @@ -176,6 +181,7 @@ class IPSecProposalSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'description', 'encryption_algorithm', 'authentication_algorithm', 'sa_lifetime_seconds', 'sa_lifetime_data', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ) + brief_fields = ('id', 'url', 'display', 'name') class IPSecPolicySerializer(NetBoxModelSerializer): @@ -199,6 +205,7 @@ class IPSecPolicySerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'description', 'proposals', 'pfs_group', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ) + brief_fields = ('id', 'url', 'display', 'name') class IPSecProfileSerializer(NetBoxModelSerializer): @@ -217,6 +224,7 @@ class IPSecProfileSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'name', 'description', 'mode', 'ike_policy', 'ipsec_policy', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ) + brief_fields = ('id', 'url', 'display', 'name') # @@ -246,6 +254,7 @@ class L2VPNSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'identifier', 'name', 'slug', 'type', 'import_targets', 'export_targets', 'description', 'comments', 'tenant', 'tags', 'custom_fields', 'created', 'last_updated' ] + brief_fields = ('id', 'url', 'display', 'identifier', 'name', 'slug', 'type') class L2VPNTerminationSerializer(NetBoxModelSerializer): @@ -262,6 +271,7 @@ class L2VPNTerminationSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'l2vpn', 'assigned_object_type', 'assigned_object_id', 'assigned_object', 'tags', 'custom_fields', 'created', 'last_updated' ] + brief_fields = ('id', 'url', 'display', 'l2vpn') @extend_schema_field(serializers.JSONField(allow_null=True)) def get_assigned_object(self, instance): diff --git a/netbox/wireless/api/serializers.py b/netbox/wireless/api/serializers.py index cc2c8701c..79a50eef7 100644 --- a/netbox/wireless/api/serializers.py +++ b/netbox/wireless/api/serializers.py @@ -28,6 +28,7 @@ class WirelessLANGroupSerializer(NestedGroupModelSerializer): 'id', 'url', 'display', 'name', 'slug', 'parent', 'description', 'tags', 'custom_fields', 'created', 'last_updated', 'wirelesslan_count', '_depth', ] + brief_fields = ('id', 'url', 'display', 'name', 'slug', 'wirelesslan_count', '_depth') class WirelessLANSerializer(NetBoxModelSerializer): @@ -45,6 +46,7 @@ class WirelessLANSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'ssid', 'description', 'group', 'status', 'vlan', 'tenant', 'auth_type', 'auth_cipher', 'auth_psk', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'ssid') class WirelessLinkSerializer(NetBoxModelSerializer): @@ -62,3 +64,4 @@ class WirelessLinkSerializer(NetBoxModelSerializer): 'id', 'url', 'display', 'interface_a', 'interface_b', 'ssid', 'status', 'tenant', 'auth_type', 'auth_cipher', 'auth_psk', 'description', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', ] + brief_fields = ('id', 'url', 'display', 'ssid')