From bbdeae0ed9bcc06fb96ffa2970272e1a3447448c Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Wed, 9 Mar 2022 11:44:55 -0500 Subject: [PATCH] Move CustomFieldModelViewSet functionality into NetBoxModelViewSet --- netbox/circuits/api/views.py | 9 +++---- netbox/dcim/api/views.py | 32 +++++++++++------------ netbox/extras/api/views.py | 18 ------------- netbox/ipam/api/views.py | 35 +++++++++++++------------- netbox/netbox/api/viewsets/__init__.py | 14 +++++++++++ netbox/tenancy/api/views.py | 16 ++++++------ netbox/virtualization/api/views.py | 11 ++++---- netbox/wireless/api/views.py | 8 +++--- 8 files changed, 69 insertions(+), 74 deletions(-) diff --git a/netbox/circuits/api/views.py b/netbox/circuits/api/views.py index 378aeeb51..99687fe9d 100644 --- a/netbox/circuits/api/views.py +++ b/netbox/circuits/api/views.py @@ -3,7 +3,6 @@ from rest_framework.routers import APIRootView from circuits import filtersets from circuits.models import * from dcim.api.views import PassThroughPortMixin -from extras.api.views import CustomFieldModelViewSet from netbox.api.viewsets import NetBoxModelViewSet from utilities.utils import count_related from . import serializers @@ -21,7 +20,7 @@ class CircuitsRootView(APIRootView): # Providers # -class ProviderViewSet(CustomFieldModelViewSet): +class ProviderViewSet(NetBoxModelViewSet): queryset = Provider.objects.prefetch_related('tags').annotate( circuit_count=count_related(Circuit, 'provider') ) @@ -33,7 +32,7 @@ class ProviderViewSet(CustomFieldModelViewSet): # Circuit Types # -class CircuitTypeViewSet(CustomFieldModelViewSet): +class CircuitTypeViewSet(NetBoxModelViewSet): queryset = CircuitType.objects.prefetch_related('tags').annotate( circuit_count=count_related(Circuit, 'type') ) @@ -45,7 +44,7 @@ class CircuitTypeViewSet(CustomFieldModelViewSet): # Circuits # -class CircuitViewSet(CustomFieldModelViewSet): +class CircuitViewSet(NetBoxModelViewSet): queryset = Circuit.objects.prefetch_related( 'type', 'tenant', 'provider', 'termination_a', 'termination_z' ).prefetch_related('tags') @@ -70,7 +69,7 @@ class CircuitTerminationViewSet(PassThroughPortMixin, NetBoxModelViewSet): # Provider networks # -class ProviderNetworkViewSet(CustomFieldModelViewSet): +class ProviderNetworkViewSet(NetBoxModelViewSet): queryset = ProviderNetwork.objects.prefetch_related('tags') serializer_class = serializers.ProviderNetworkSerializer filterset_class = filtersets.ProviderNetworkFilterSet diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 077d7c753..e99ef333a 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -14,7 +14,7 @@ from rest_framework.viewsets import ViewSet from circuits.models import Circuit from dcim import filtersets from dcim.models import * -from extras.api.views import ConfigContextQuerySetMixin, CustomFieldModelViewSet +from extras.api.views import ConfigContextQuerySetMixin from ipam.models import Prefix, VLAN from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired from netbox.api.exceptions import ServiceUnavailable @@ -103,7 +103,7 @@ class PassThroughPortMixin(object): # Regions # -class RegionViewSet(CustomFieldModelViewSet): +class RegionViewSet(NetBoxModelViewSet): queryset = Region.objects.add_related_count( Region.objects.all(), Site, @@ -119,7 +119,7 @@ class RegionViewSet(CustomFieldModelViewSet): # Site groups # -class SiteGroupViewSet(CustomFieldModelViewSet): +class SiteGroupViewSet(NetBoxModelViewSet): queryset = SiteGroup.objects.add_related_count( SiteGroup.objects.all(), Site, @@ -135,7 +135,7 @@ class SiteGroupViewSet(CustomFieldModelViewSet): # Sites # -class SiteViewSet(CustomFieldModelViewSet): +class SiteViewSet(NetBoxModelViewSet): queryset = Site.objects.prefetch_related( 'region', 'tenant', 'asns', 'tags' ).annotate( @@ -154,7 +154,7 @@ class SiteViewSet(CustomFieldModelViewSet): # Locations # -class LocationViewSet(CustomFieldModelViewSet): +class LocationViewSet(NetBoxModelViewSet): queryset = Location.objects.add_related_count( Location.objects.add_related_count( Location.objects.all(), @@ -176,7 +176,7 @@ class LocationViewSet(CustomFieldModelViewSet): # Rack roles # -class RackRoleViewSet(CustomFieldModelViewSet): +class RackRoleViewSet(NetBoxModelViewSet): queryset = RackRole.objects.prefetch_related('tags').annotate( rack_count=count_related(Rack, 'role') ) @@ -188,7 +188,7 @@ class RackRoleViewSet(CustomFieldModelViewSet): # Racks # -class RackViewSet(CustomFieldModelViewSet): +class RackViewSet(NetBoxModelViewSet): queryset = Rack.objects.prefetch_related( 'site', 'location', 'role', 'tenant', 'tags' ).annotate( @@ -260,7 +260,7 @@ class RackReservationViewSet(NetBoxModelViewSet): # Manufacturers # -class ManufacturerViewSet(CustomFieldModelViewSet): +class ManufacturerViewSet(NetBoxModelViewSet): queryset = Manufacturer.objects.prefetch_related('tags').annotate( devicetype_count=count_related(DeviceType, 'manufacturer'), inventoryitem_count=count_related(InventoryItem, 'manufacturer'), @@ -274,7 +274,7 @@ class ManufacturerViewSet(CustomFieldModelViewSet): # Device/module types # -class DeviceTypeViewSet(CustomFieldModelViewSet): +class DeviceTypeViewSet(NetBoxModelViewSet): queryset = DeviceType.objects.prefetch_related('manufacturer', 'tags').annotate( device_count=count_related(Device, 'device_type') ) @@ -283,7 +283,7 @@ class DeviceTypeViewSet(CustomFieldModelViewSet): brief_prefetch_fields = ['manufacturer'] -class ModuleTypeViewSet(CustomFieldModelViewSet): +class ModuleTypeViewSet(NetBoxModelViewSet): queryset = ModuleType.objects.prefetch_related('manufacturer', 'tags').annotate( # module_count=count_related(Module, 'module_type') ) @@ -360,7 +360,7 @@ class InventoryItemTemplateViewSet(NetBoxModelViewSet): # Device roles # -class DeviceRoleViewSet(CustomFieldModelViewSet): +class DeviceRoleViewSet(NetBoxModelViewSet): queryset = DeviceRole.objects.prefetch_related('tags').annotate( device_count=count_related(Device, 'device_role'), virtualmachine_count=count_related(VirtualMachine, 'role') @@ -373,7 +373,7 @@ class DeviceRoleViewSet(CustomFieldModelViewSet): # Platforms # -class PlatformViewSet(CustomFieldModelViewSet): +class PlatformViewSet(NetBoxModelViewSet): queryset = Platform.objects.prefetch_related('tags').annotate( device_count=count_related(Device, 'platform'), virtualmachine_count=count_related(VirtualMachine, 'platform') @@ -386,7 +386,7 @@ class PlatformViewSet(CustomFieldModelViewSet): # Devices/modules # -class DeviceViewSet(ConfigContextQuerySetMixin, CustomFieldModelViewSet): +class DeviceViewSet(ConfigContextQuerySetMixin, NetBoxModelViewSet): queryset = Device.objects.prefetch_related( 'device_type__manufacturer', 'device_role', 'tenant', 'platform', 'site', 'location', 'rack', 'parent_bay', 'virtual_chassis__master', 'primary_ip4__nat_outside', 'primary_ip6__nat_outside', 'tags', @@ -532,7 +532,7 @@ class DeviceViewSet(ConfigContextQuerySetMixin, CustomFieldModelViewSet): return Response(response) -class ModuleViewSet(CustomFieldModelViewSet): +class ModuleViewSet(NetBoxModelViewSet): queryset = Module.objects.prefetch_related( 'device', 'module_bay', 'module_type__manufacturer', 'tags', ) @@ -633,7 +633,7 @@ class InventoryItemViewSet(NetBoxModelViewSet): # Device component roles # -class InventoryItemRoleViewSet(CustomFieldModelViewSet): +class InventoryItemRoleViewSet(NetBoxModelViewSet): queryset = InventoryItemRole.objects.prefetch_related('tags').annotate( inventoryitem_count=count_related(InventoryItem, 'role') ) @@ -685,7 +685,7 @@ class PowerPanelViewSet(NetBoxModelViewSet): # Power feeds # -class PowerFeedViewSet(PathEndpointMixin, CustomFieldModelViewSet): +class PowerFeedViewSet(PathEndpointMixin, NetBoxModelViewSet): queryset = PowerFeed.objects.prefetch_related( 'power_panel', 'rack', '_path__destination', 'cable', '_link_peer', 'tags' ) diff --git a/netbox/extras/api/views.py b/netbox/extras/api/views.py index 1e7f46a86..4f42b4c93 100644 --- a/netbox/extras/api/views.py +++ b/netbox/extras/api/views.py @@ -76,24 +76,6 @@ class CustomFieldViewSet(NetBoxModelViewSet): filterset_class = filtersets.CustomFieldFilterSet -class CustomFieldModelViewSet(NetBoxModelViewSet): - """ - Include the applicable set of CustomFields in the ModelViewSet context. - """ - - def get_serializer_context(self): - - # Gather all custom fields for the model - content_type = ContentType.objects.get_for_model(self.queryset.model) - custom_fields = content_type.custom_fields.all() - - context = super().get_serializer_context() - context.update({ - 'custom_fields': custom_fields, - }) - return context - - # # Custom links # diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py index 445771215..c09cffa05 100644 --- a/netbox/ipam/api/views.py +++ b/netbox/ipam/api/views.py @@ -1,18 +1,17 @@ from django.core.exceptions import ObjectDoesNotExist, PermissionDenied from django.db import transaction -from django_pglocks import advisory_lock from django.shortcuts import get_object_or_404 +from django_pglocks import advisory_lock from drf_yasg.utils import swagger_auto_schema from rest_framework import status from rest_framework.response import Response from rest_framework.routers import APIRootView from rest_framework.views import APIView - from dcim.models import Site -from extras.api.views import CustomFieldModelViewSet from ipam import filtersets from ipam.models import * +from netbox.api.viewsets import NetBoxModelViewSet from netbox.api.viewsets.mixins import ObjectValidationMixin from netbox.config import get_config from utilities.constants import ADVISORY_LOCK_KEYS @@ -32,13 +31,13 @@ class IPAMRootView(APIRootView): # Viewsets # -class ASNViewSet(CustomFieldModelViewSet): +class ASNViewSet(NetBoxModelViewSet): queryset = ASN.objects.prefetch_related('tenant', 'rir').annotate(site_count=count_related(Site, 'asns')) serializer_class = serializers.ASNSerializer filterset_class = filtersets.ASNFilterSet -class VRFViewSet(CustomFieldModelViewSet): +class VRFViewSet(NetBoxModelViewSet): queryset = VRF.objects.prefetch_related('tenant').prefetch_related( 'import_targets', 'export_targets', 'tags' ).annotate( @@ -49,13 +48,13 @@ class VRFViewSet(CustomFieldModelViewSet): filterset_class = filtersets.VRFFilterSet -class RouteTargetViewSet(CustomFieldModelViewSet): +class RouteTargetViewSet(NetBoxModelViewSet): queryset = RouteTarget.objects.prefetch_related('tenant').prefetch_related('tags') serializer_class = serializers.RouteTargetSerializer filterset_class = filtersets.RouteTargetFilterSet -class RIRViewSet(CustomFieldModelViewSet): +class RIRViewSet(NetBoxModelViewSet): queryset = RIR.objects.annotate( aggregate_count=count_related(Aggregate, 'rir') ).prefetch_related('tags') @@ -63,13 +62,13 @@ class RIRViewSet(CustomFieldModelViewSet): filterset_class = filtersets.RIRFilterSet -class AggregateViewSet(CustomFieldModelViewSet): +class AggregateViewSet(NetBoxModelViewSet): queryset = Aggregate.objects.prefetch_related('rir').prefetch_related('tags') serializer_class = serializers.AggregateSerializer filterset_class = filtersets.AggregateFilterSet -class RoleViewSet(CustomFieldModelViewSet): +class RoleViewSet(NetBoxModelViewSet): queryset = Role.objects.annotate( prefix_count=count_related(Prefix, 'role'), vlan_count=count_related(VLAN, 'role') @@ -78,7 +77,7 @@ class RoleViewSet(CustomFieldModelViewSet): filterset_class = filtersets.RoleFilterSet -class PrefixViewSet(CustomFieldModelViewSet): +class PrefixViewSet(NetBoxModelViewSet): queryset = Prefix.objects.prefetch_related( 'site', 'vrf__tenant', 'tenant', 'vlan', 'role', 'tags' ) @@ -93,7 +92,7 @@ class PrefixViewSet(CustomFieldModelViewSet): return super().get_serializer_class() -class IPRangeViewSet(CustomFieldModelViewSet): +class IPRangeViewSet(NetBoxModelViewSet): queryset = IPRange.objects.prefetch_related('vrf', 'role', 'tenant', 'tags') serializer_class = serializers.IPRangeSerializer filterset_class = filtersets.IPRangeFilterSet @@ -101,7 +100,7 @@ class IPRangeViewSet(CustomFieldModelViewSet): parent_model = IPRange # AvailableIPsMixin -class IPAddressViewSet(CustomFieldModelViewSet): +class IPAddressViewSet(NetBoxModelViewSet): queryset = IPAddress.objects.prefetch_related( 'vrf__tenant', 'tenant', 'nat_inside', 'nat_outside', 'tags', 'assigned_object' ) @@ -109,20 +108,20 @@ class IPAddressViewSet(CustomFieldModelViewSet): filterset_class = filtersets.IPAddressFilterSet -class FHRPGroupViewSet(CustomFieldModelViewSet): +class FHRPGroupViewSet(NetBoxModelViewSet): queryset = FHRPGroup.objects.prefetch_related('ip_addresses', 'tags') serializer_class = serializers.FHRPGroupSerializer filterset_class = filtersets.FHRPGroupFilterSet brief_prefetch_fields = ('ip_addresses',) -class FHRPGroupAssignmentViewSet(CustomFieldModelViewSet): +class FHRPGroupAssignmentViewSet(NetBoxModelViewSet): queryset = FHRPGroupAssignment.objects.prefetch_related('group', 'interface') serializer_class = serializers.FHRPGroupAssignmentSerializer filterset_class = filtersets.FHRPGroupAssignmentFilterSet -class VLANGroupViewSet(CustomFieldModelViewSet): +class VLANGroupViewSet(NetBoxModelViewSet): queryset = VLANGroup.objects.annotate( vlan_count=count_related(VLAN, 'group') ).prefetch_related('tags') @@ -130,7 +129,7 @@ class VLANGroupViewSet(CustomFieldModelViewSet): filterset_class = filtersets.VLANGroupFilterSet -class VLANViewSet(CustomFieldModelViewSet): +class VLANViewSet(NetBoxModelViewSet): queryset = VLAN.objects.prefetch_related( 'site', 'group', 'tenant', 'role', 'tags' ).annotate( @@ -140,13 +139,13 @@ class VLANViewSet(CustomFieldModelViewSet): filterset_class = filtersets.VLANFilterSet -class ServiceTemplateViewSet(CustomFieldModelViewSet): +class ServiceTemplateViewSet(NetBoxModelViewSet): queryset = ServiceTemplate.objects.prefetch_related('tags') serializer_class = serializers.ServiceTemplateSerializer filterset_class = filtersets.ServiceTemplateFilterSet -class ServiceViewSet(CustomFieldModelViewSet): +class ServiceViewSet(NetBoxModelViewSet): queryset = Service.objects.prefetch_related( 'device', 'virtual_machine', 'tags', 'ipaddresses' ) diff --git a/netbox/netbox/api/viewsets/__init__.py b/netbox/netbox/api/viewsets/__init__.py index 05bd8cb19..462c07c6f 100644 --- a/netbox/netbox/api/viewsets/__init__.py +++ b/netbox/netbox/api/viewsets/__init__.py @@ -70,6 +70,20 @@ class NetBoxModelViewSet(BulkUpdateModelMixin, BulkDestroyModelMixin, ObjectVali logger.debug(f"Using serializer {self.serializer_class}") return self.serializer_class + def get_serializer_context(self): + """ + For models which support custom fields, populate the `custom_fields` context. + """ + context = super().get_serializer_context() + + if hasattr(self.queryset.model, 'custom_fields'): + content_type = ContentType.objects.get_for_model(self.queryset.model) + context.update({ + 'custom_fields': content_type.custom_fields.all(), + }) + + return context + def get_queryset(self): # If using brief mode, clear all prefetches from the queryset and append only brief_prefetch_fields (if any) if self.brief: diff --git a/netbox/tenancy/api/views.py b/netbox/tenancy/api/views.py index fbc166bdb..39c86d80e 100644 --- a/netbox/tenancy/api/views.py +++ b/netbox/tenancy/api/views.py @@ -1,9 +1,9 @@ from rest_framework.routers import APIRootView from circuits.models import Circuit -from dcim.models import Device, Rack, Site, Cable -from extras.api.views import CustomFieldModelViewSet +from dcim.models import Device, Rack, Site from ipam.models import IPAddress, Prefix, VLAN, VRF +from netbox.api.viewsets import NetBoxModelViewSet from tenancy import filtersets from tenancy.models import * from utilities.utils import count_related @@ -23,7 +23,7 @@ class TenancyRootView(APIRootView): # Tenants # -class TenantGroupViewSet(CustomFieldModelViewSet): +class TenantGroupViewSet(NetBoxModelViewSet): queryset = TenantGroup.objects.add_related_count( TenantGroup.objects.all(), Tenant, @@ -35,7 +35,7 @@ class TenantGroupViewSet(CustomFieldModelViewSet): filterset_class = filtersets.TenantGroupFilterSet -class TenantViewSet(CustomFieldModelViewSet): +class TenantViewSet(NetBoxModelViewSet): queryset = Tenant.objects.prefetch_related( 'group', 'tags' ).annotate( @@ -58,7 +58,7 @@ class TenantViewSet(CustomFieldModelViewSet): # Contacts # -class ContactGroupViewSet(CustomFieldModelViewSet): +class ContactGroupViewSet(NetBoxModelViewSet): queryset = ContactGroup.objects.add_related_count( ContactGroup.objects.all(), Contact, @@ -70,19 +70,19 @@ class ContactGroupViewSet(CustomFieldModelViewSet): filterset_class = filtersets.ContactGroupFilterSet -class ContactRoleViewSet(CustomFieldModelViewSet): +class ContactRoleViewSet(NetBoxModelViewSet): queryset = ContactRole.objects.prefetch_related('tags') serializer_class = serializers.ContactRoleSerializer filterset_class = filtersets.ContactRoleFilterSet -class ContactViewSet(CustomFieldModelViewSet): +class ContactViewSet(NetBoxModelViewSet): queryset = Contact.objects.prefetch_related('group', 'tags') serializer_class = serializers.ContactSerializer filterset_class = filtersets.ContactFilterSet -class ContactAssignmentViewSet(CustomFieldModelViewSet): +class ContactAssignmentViewSet(NetBoxModelViewSet): queryset = ContactAssignment.objects.prefetch_related('object', 'contact', 'role') serializer_class = serializers.ContactAssignmentSerializer filterset_class = filtersets.ContactAssignmentFilterSet diff --git a/netbox/virtualization/api/views.py b/netbox/virtualization/api/views.py index 91b4fbbab..665114881 100644 --- a/netbox/virtualization/api/views.py +++ b/netbox/virtualization/api/views.py @@ -1,7 +1,8 @@ from rest_framework.routers import APIRootView from dcim.models import Device -from extras.api.views import ConfigContextQuerySetMixin, CustomFieldModelViewSet, NetBoxModelViewSet +from extras.api.views import ConfigContextQuerySetMixin +from netbox.api.viewsets import NetBoxModelViewSet from utilities.utils import count_related from virtualization import filtersets from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface @@ -20,7 +21,7 @@ class VirtualizationRootView(APIRootView): # Clusters # -class ClusterTypeViewSet(CustomFieldModelViewSet): +class ClusterTypeViewSet(NetBoxModelViewSet): queryset = ClusterType.objects.annotate( cluster_count=count_related(Cluster, 'type') ).prefetch_related('tags') @@ -28,7 +29,7 @@ class ClusterTypeViewSet(CustomFieldModelViewSet): filterset_class = filtersets.ClusterTypeFilterSet -class ClusterGroupViewSet(CustomFieldModelViewSet): +class ClusterGroupViewSet(NetBoxModelViewSet): queryset = ClusterGroup.objects.annotate( cluster_count=count_related(Cluster, 'group') ).prefetch_related('tags') @@ -36,7 +37,7 @@ class ClusterGroupViewSet(CustomFieldModelViewSet): filterset_class = filtersets.ClusterGroupFilterSet -class ClusterViewSet(CustomFieldModelViewSet): +class ClusterViewSet(NetBoxModelViewSet): queryset = Cluster.objects.prefetch_related( 'type', 'group', 'tenant', 'site', 'tags' ).annotate( @@ -51,7 +52,7 @@ class ClusterViewSet(CustomFieldModelViewSet): # Virtual machines # -class VirtualMachineViewSet(ConfigContextQuerySetMixin, CustomFieldModelViewSet): +class VirtualMachineViewSet(ConfigContextQuerySetMixin, NetBoxModelViewSet): queryset = VirtualMachine.objects.prefetch_related( 'cluster__site', 'role', 'tenant', 'platform', 'primary_ip4', 'primary_ip6', 'tags' ) diff --git a/netbox/wireless/api/views.py b/netbox/wireless/api/views.py index 734f6940f..77a766c50 100644 --- a/netbox/wireless/api/views.py +++ b/netbox/wireless/api/views.py @@ -1,6 +1,6 @@ from rest_framework.routers import APIRootView -from extras.api.views import CustomFieldModelViewSet +from netbox.api.viewsets import NetBoxModelViewSet from wireless import filtersets from wireless.models import * from . import serializers @@ -14,7 +14,7 @@ class WirelessRootView(APIRootView): return 'Wireless' -class WirelessLANGroupViewSet(CustomFieldModelViewSet): +class WirelessLANGroupViewSet(NetBoxModelViewSet): queryset = WirelessLANGroup.objects.add_related_count( WirelessLANGroup.objects.all(), WirelessLAN, @@ -26,13 +26,13 @@ class WirelessLANGroupViewSet(CustomFieldModelViewSet): filterset_class = filtersets.WirelessLANGroupFilterSet -class WirelessLANViewSet(CustomFieldModelViewSet): +class WirelessLANViewSet(NetBoxModelViewSet): queryset = WirelessLAN.objects.prefetch_related('vlan', 'tags') serializer_class = serializers.WirelessLANSerializer filterset_class = filtersets.WirelessLANFilterSet -class WirelessLinkViewSet(CustomFieldModelViewSet): +class WirelessLinkViewSet(NetBoxModelViewSet): queryset = WirelessLink.objects.prefetch_related('interface_a', 'interface_b', 'tags') serializer_class = serializers.WirelessLinkSerializer filterset_class = filtersets.WirelessLinkFilterSet