diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py index 033dd3188..c81095d29 100644 --- a/netbox/dcim/api/serializers.py +++ b/netbox/dcim/api/serializers.py @@ -72,20 +72,20 @@ class SiteSerializer(TaggitSerializer, CustomFieldModelSerializer): tenant = NestedTenantSerializer(required=False, allow_null=True) time_zone = TimeZoneField(required=False) tags = TagListSerializerField(required=False) - prefix_count = serializers.IntegerField(read_only=True) - vlan_count = serializers.IntegerField(read_only=True) - rack_count = serializers.IntegerField(read_only=True) - device_count = serializers.IntegerField(read_only=True) circuit_count = serializers.IntegerField(read_only=True) + device_count = serializers.IntegerField(read_only=True) + prefix_count = serializers.IntegerField(read_only=True) + rack_count = serializers.IntegerField(read_only=True) virtualmachine_count = serializers.IntegerField(read_only=True) + vlan_count = serializers.IntegerField(read_only=True) class Meta: model = Site fields = [ 'id', 'name', 'slug', 'status', 'region', 'tenant', 'facility', 'asn', 'time_zone', 'description', 'physical_address', 'shipping_address', 'latitude', 'longitude', 'contact_name', 'contact_phone', - 'contact_email', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'prefix_count', - 'vlan_count', 'rack_count', 'device_count', 'circuit_count', 'virtualmachine_count', + 'contact_email', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'circuit_count', + 'device_count', 'prefix_count', 'rack_count', 'virtualmachine_count', 'vlan_count', ] @@ -121,13 +121,14 @@ class RackSerializer(TaggitSerializer, CustomFieldModelSerializer): outer_unit = ChoiceField(choices=RACK_DIMENSION_UNIT_CHOICES, required=False) tags = TagListSerializerField(required=False) device_count = serializers.IntegerField(read_only=True) + powerfeed_count = serializers.IntegerField(read_only=True) class Meta: model = Rack fields = [ 'id', 'name', 'facility_id', 'display_name', 'site', 'group', 'tenant', 'status', 'role', 'serial', 'asset_tag', 'type', 'width', 'u_height', 'desc_units', 'outer_width', 'outer_depth', 'outer_unit', - 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'device_count', + 'comments', 'tags', 'custom_fields', 'created', 'last_updated', 'device_count', 'powerfeed_count', ] # Omit the UniqueTogetherValidator that would be automatically added to validate (group, facility_id). This # prevents facility_id from being interpreted as a required field. @@ -175,10 +176,12 @@ class RackReservationSerializer(ValidatedModelSerializer): class ManufacturerSerializer(ValidatedModelSerializer): devicetype_count = serializers.IntegerField(read_only=True) + inventoryitem_count = serializers.IntegerField(read_only=True) + platform_count = serializers.IntegerField(read_only=True) class Meta: model = Manufacturer - fields = ['id', 'name', 'slug', 'devicetype_count'] + fields = ['id', 'name', 'slug', 'devicetype_count', 'inventoryitem_count', 'platform_count'] class DeviceTypeSerializer(TaggitSerializer, CustomFieldModelSerializer): diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index 16373c83f..0f6d143c8 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -165,11 +165,12 @@ class RackRoleViewSet(ModelViewSet): class RackViewSet(CustomFieldModelViewSet): queryset = Rack.objects.select_related( - 'site', 'group__site', 'tenant' + 'site', 'group__site', 'role', 'tenant' ).prefetch_related( 'tags' ).annotate( - device_count=Count('devices') + device_count=get_subquery(Device, 'rack'), + powerfeed_count=get_subquery(PowerFeed, 'rack') ) serializer_class = serializers.RackSerializer filterset_class = filters.RackFilter @@ -220,7 +221,9 @@ class RackReservationViewSet(ModelViewSet): class ManufacturerViewSet(ModelViewSet): queryset = Manufacturer.objects.annotate( - devicetype_count=Count('device_types') + devicetype_count=get_subquery(DeviceType, 'manufacturer'), + inventoryitem_count=get_subquery(InventoryItem, 'manufacturer'), + platform_count=get_subquery(Platform, 'manufacturer') ) serializer_class = serializers.ManufacturerSerializer filterset_class = filters.ManufacturerFilter diff --git a/netbox/ipam/api/serializers.py b/netbox/ipam/api/serializers.py index 8587c086b..02e36c63c 100644 --- a/netbox/ipam/api/serializers.py +++ b/netbox/ipam/api/serializers.py @@ -25,13 +25,14 @@ from .nested_serializers import * class VRFSerializer(TaggitSerializer, CustomFieldModelSerializer): tenant = NestedTenantSerializer(required=False, allow_null=True) tags = TagListSerializerField(required=False) + ipaddress_count = serializers.IntegerField(read_only=True) prefix_count = serializers.IntegerField(read_only=True) class Meta: model = VRF fields = [ 'id', 'name', 'rd', 'tenant', 'enforce_unique', 'description', 'tags', 'display_name', 'custom_fields', - 'created', 'last_updated', 'prefix_count', + 'created', 'last_updated', 'ipaddress_count', 'prefix_count', ] @@ -104,12 +105,13 @@ class VLANSerializer(TaggitSerializer, CustomFieldModelSerializer): status = ChoiceField(choices=VLAN_STATUS_CHOICES, required=False) role = NestedRoleSerializer(required=False, allow_null=True) tags = TagListSerializerField(required=False) + prefix_count = serializers.IntegerField(read_only=True) class Meta: model = VLAN fields = [ 'id', 'site', 'group', 'vid', 'name', 'tenant', 'status', 'role', 'description', 'tags', 'display_name', - 'custom_fields', 'created', 'last_updated', + 'custom_fields', 'created', 'last_updated', 'prefix_count', ] validators = [] diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py index 7ba319cbb..b84466cbb 100644 --- a/netbox/ipam/api/views.py +++ b/netbox/ipam/api/views.py @@ -34,7 +34,8 @@ class IPAMFieldChoicesViewSet(FieldChoicesViewSet): class VRFViewSet(CustomFieldModelViewSet): queryset = VRF.objects.select_related('tenant').prefetch_related('tags').annotate( - prefix_count=Count('prefixes') + ipaddress_count=get_subquery(IPAddress, 'vrf'), + prefix_count=get_subquery(Prefix, 'vrf') ) serializer_class = serializers.VRFSerializer filterset_class = filters.VRFFilter @@ -288,7 +289,13 @@ class VLANGroupViewSet(ModelViewSet): # class VLANViewSet(CustomFieldModelViewSet): - queryset = VLAN.objects.select_related('site', 'group', 'tenant', 'role').prefetch_related('tags') + queryset = VLAN.objects.select_related( + 'site', 'group', 'tenant', 'role' + ).prefetch_related( + 'tags' + ).annotate( + prefix_count=get_subquery(Prefix, 'role') + ) serializer_class = serializers.VLANSerializer filterset_class = filters.VLANFilter diff --git a/netbox/tenancy/api/serializers.py b/netbox/tenancy/api/serializers.py index b00c6cf3d..28ae04694 100644 --- a/netbox/tenancy/api/serializers.py +++ b/netbox/tenancy/api/serializers.py @@ -22,10 +22,20 @@ class TenantGroupSerializer(ValidatedModelSerializer): class TenantSerializer(TaggitSerializer, CustomFieldModelSerializer): group = NestedTenantGroupSerializer(required=False) tags = TagListSerializerField(required=False) + circuit_count = serializers.IntegerField(read_only=True) + device_count = serializers.IntegerField(read_only=True) + ipaddress_count = serializers.IntegerField(read_only=True) + prefix_count = serializers.IntegerField(read_only=True) + rack_count = serializers.IntegerField(read_only=True) + site_count = serializers.IntegerField(read_only=True) + virtualmachine_count = serializers.IntegerField(read_only=True) + vlan_count = serializers.IntegerField(read_only=True) + vrf_count = serializers.IntegerField(read_only=True) class Meta: model = Tenant fields = [ 'id', 'name', 'slug', 'group', 'description', 'comments', 'tags', 'custom_fields', 'created', - 'last_updated', + 'last_updated', 'circuit_count', 'device_count', 'ipaddress_count', 'prefix_count', 'rack_count', + 'site_count', 'virtualmachine_count', 'vlan_count', 'vrf_count', ] diff --git a/netbox/tenancy/api/views.py b/netbox/tenancy/api/views.py index 32015e316..b79a076f1 100644 --- a/netbox/tenancy/api/views.py +++ b/netbox/tenancy/api/views.py @@ -1,9 +1,12 @@ -from django.db.models import Count - +from circuits.models import Circuit +from dcim.models import Device, Rack, Site from extras.api.views import CustomFieldModelViewSet +from ipam.models import IPAddress, Prefix, VLAN, VRF from tenancy import filters from tenancy.models import Tenant, TenantGroup from utilities.api import FieldChoicesViewSet, ModelViewSet +from utilities.utils import get_subquery +from virtualization.models import VirtualMachine from . import serializers @@ -21,7 +24,7 @@ class TenancyFieldChoicesViewSet(FieldChoicesViewSet): class TenantGroupViewSet(ModelViewSet): queryset = TenantGroup.objects.annotate( - tenant_count=Count('tenants') + tenant_count=get_subquery(Tenant, 'group') ) serializer_class = serializers.TenantGroupSerializer filterset_class = filters.TenantGroupFilter @@ -32,6 +35,20 @@ class TenantGroupViewSet(ModelViewSet): # class TenantViewSet(CustomFieldModelViewSet): - queryset = Tenant.objects.select_related('group').prefetch_related('tags') + queryset = Tenant.objects.select_related( + 'group' + ).prefetch_related( + 'tags' + ).annotate( + circuit_count=get_subquery(Circuit, 'tenant'), + device_count=get_subquery(Device, 'tenant'), + ipaddress_count=get_subquery(IPAddress, 'tenant'), + prefix_count=get_subquery(Prefix, 'tenant'), + rack_count=get_subquery(Rack, 'tenant'), + site_count=get_subquery(Site, 'tenant'), + virtualmachine_count=get_subquery(VirtualMachine, 'tenant'), + vlan_count=get_subquery(VLAN, 'tenant'), + vrf_count=get_subquery(VRF, 'tenant') + ) serializer_class = serializers.TenantSerializer filterset_class = filters.TenantFilter diff --git a/netbox/virtualization/api/serializers.py b/netbox/virtualization/api/serializers.py index 18b8e878e..0b98ce44a 100644 --- a/netbox/virtualization/api/serializers.py +++ b/netbox/virtualization/api/serializers.py @@ -40,13 +40,14 @@ class ClusterSerializer(TaggitSerializer, CustomFieldModelSerializer): group = NestedClusterGroupSerializer(required=False, allow_null=True) site = NestedSiteSerializer(required=False, allow_null=True) tags = TagListSerializerField(required=False) + device_count = serializers.IntegerField(read_only=True) virtualmachine_count = serializers.IntegerField(read_only=True) class Meta: model = Cluster fields = [ 'id', 'name', 'type', 'group', 'site', 'comments', 'tags', 'custom_fields', 'created', 'last_updated', - 'virtualmachine_count', + 'device_count', 'virtualmachine_count', ] diff --git a/netbox/virtualization/api/views.py b/netbox/virtualization/api/views.py index 9ce505310..552d5e93f 100644 --- a/netbox/virtualization/api/views.py +++ b/netbox/virtualization/api/views.py @@ -1,8 +1,9 @@ from django.db.models import Count -from dcim.models import Interface +from dcim.models import Device, Interface from extras.api.views import CustomFieldModelViewSet from utilities.api import FieldChoicesViewSet, ModelViewSet +from utilities.utils import get_subquery from virtualization import filters from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine from . import serializers @@ -39,8 +40,13 @@ class ClusterGroupViewSet(ModelViewSet): class ClusterViewSet(CustomFieldModelViewSet): - queryset = Cluster.objects.select_related('type', 'group').prefetch_related('tags').annotate( - virtualmachine_count=Count('virtual_machines') + queryset = Cluster.objects.select_related( + 'type', 'group', 'site', + ).prefetch_related( + 'tags' + ).annotate( + device_count=get_subquery(Device, 'cluster'), + virtualmachine_count=get_subquery(VirtualMachine, 'cluster') ) serializer_class = serializers.ClusterSerializer filterset_class = filters.ClusterFilter