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

Rename get_subquery() to count_related()

Jeremy Stretch 5 лет назад
Родитель
Сommit
4a066a1913

+ 3 - 3
netbox/circuits/api/views.py

@@ -6,7 +6,7 @@ from circuits.models import Provider, CircuitTermination, CircuitType, Circuit
 from dcim.api.views import PathEndpointMixin
 from dcim.api.views import PathEndpointMixin
 from extras.api.views import CustomFieldModelViewSet
 from extras.api.views import CustomFieldModelViewSet
 from netbox.api.views import ModelViewSet
 from netbox.api.views import ModelViewSet
-from utilities.utils import get_subquery
+from utilities.utils import count_related
 from . import serializers
 from . import serializers
 
 
 
 
@@ -24,7 +24,7 @@ class CircuitsRootView(APIRootView):
 
 
 class ProviderViewSet(CustomFieldModelViewSet):
 class ProviderViewSet(CustomFieldModelViewSet):
     queryset = Provider.objects.prefetch_related('tags').annotate(
     queryset = Provider.objects.prefetch_related('tags').annotate(
-        circuit_count=get_subquery(Circuit, 'provider')
+        circuit_count=count_related(Circuit, 'provider')
     )
     )
     serializer_class = serializers.ProviderSerializer
     serializer_class = serializers.ProviderSerializer
     filterset_class = filters.ProviderFilterSet
     filterset_class = filters.ProviderFilterSet
@@ -36,7 +36,7 @@ class ProviderViewSet(CustomFieldModelViewSet):
 
 
 class CircuitTypeViewSet(ModelViewSet):
 class CircuitTypeViewSet(ModelViewSet):
     queryset = CircuitType.objects.annotate(
     queryset = CircuitType.objects.annotate(
-        circuit_count=get_subquery(Circuit, 'type')
+        circuit_count=count_related(Circuit, 'type')
     )
     )
     serializer_class = serializers.CircuitTypeSerializer
     serializer_class = serializers.CircuitTypeSerializer
     filterset_class = filters.CircuitTypeFilterSet
     filterset_class = filters.CircuitTypeFilterSet

+ 6 - 6
netbox/circuits/views.py

@@ -6,7 +6,7 @@ from django_tables2 import RequestConfig
 from netbox.views import generic
 from netbox.views import generic
 from utilities.forms import ConfirmationForm
 from utilities.forms import ConfirmationForm
 from utilities.paginator import EnhancedPaginator, get_paginate_count
 from utilities.paginator import EnhancedPaginator, get_paginate_count
-from utilities.utils import get_subquery
+from utilities.utils import count_related
 from . import filters, forms, tables
 from . import filters, forms, tables
 from .choices import CircuitTerminationSideChoices
 from .choices import CircuitTerminationSideChoices
 from .models import Circuit, CircuitTermination, CircuitType, Provider
 from .models import Circuit, CircuitTermination, CircuitType, Provider
@@ -18,7 +18,7 @@ from .models import Circuit, CircuitTermination, CircuitType, Provider
 
 
 class ProviderListView(generic.ObjectListView):
 class ProviderListView(generic.ObjectListView):
     queryset = Provider.objects.annotate(
     queryset = Provider.objects.annotate(
-        count_circuits=get_subquery(Circuit, 'provider')
+        count_circuits=count_related(Circuit, 'provider')
     )
     )
     filterset = filters.ProviderFilterSet
     filterset = filters.ProviderFilterSet
     filterset_form = forms.ProviderFilterForm
     filterset_form = forms.ProviderFilterForm
@@ -67,7 +67,7 @@ class ProviderBulkImportView(generic.BulkImportView):
 
 
 class ProviderBulkEditView(generic.BulkEditView):
 class ProviderBulkEditView(generic.BulkEditView):
     queryset = Provider.objects.annotate(
     queryset = Provider.objects.annotate(
-        count_circuits=get_subquery(Circuit, 'provider')
+        count_circuits=count_related(Circuit, 'provider')
     )
     )
     filterset = filters.ProviderFilterSet
     filterset = filters.ProviderFilterSet
     table = tables.ProviderTable
     table = tables.ProviderTable
@@ -76,7 +76,7 @@ class ProviderBulkEditView(generic.BulkEditView):
 
 
 class ProviderBulkDeleteView(generic.BulkDeleteView):
 class ProviderBulkDeleteView(generic.BulkDeleteView):
     queryset = Provider.objects.annotate(
     queryset = Provider.objects.annotate(
-        count_circuits=get_subquery(Circuit, 'provider')
+        count_circuits=count_related(Circuit, 'provider')
     )
     )
     filterset = filters.ProviderFilterSet
     filterset = filters.ProviderFilterSet
     table = tables.ProviderTable
     table = tables.ProviderTable
@@ -88,7 +88,7 @@ class ProviderBulkDeleteView(generic.BulkDeleteView):
 
 
 class CircuitTypeListView(generic.ObjectListView):
 class CircuitTypeListView(generic.ObjectListView):
     queryset = CircuitType.objects.annotate(
     queryset = CircuitType.objects.annotate(
-        circuit_count=get_subquery(Circuit, 'type')
+        circuit_count=count_related(Circuit, 'type')
     )
     )
     table = tables.CircuitTypeTable
     table = tables.CircuitTypeTable
 
 
@@ -110,7 +110,7 @@ class CircuitTypeBulkImportView(generic.BulkImportView):
 
 
 class CircuitTypeBulkDeleteView(generic.BulkDeleteView):
 class CircuitTypeBulkDeleteView(generic.BulkDeleteView):
     queryset = CircuitType.objects.annotate(
     queryset = CircuitType.objects.annotate(
-        circuit_count=get_subquery(Circuit, 'type')
+        circuit_count=count_related(Circuit, 'type')
     )
     )
     table = tables.CircuitTypeTable
     table = tables.CircuitTypeTable
 
 

+ 20 - 20
netbox/dcim/api/views.py

@@ -30,7 +30,7 @@ from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired
 from netbox.api.exceptions import ServiceUnavailable
 from netbox.api.exceptions import ServiceUnavailable
 from netbox.api.metadata import ContentTypeMetadata
 from netbox.api.metadata import ContentTypeMetadata
 from utilities.api import get_serializer_for_model
 from utilities.api import get_serializer_for_model
-from utilities.utils import get_subquery
+from utilities.utils import count_related
 from virtualization.models import VirtualMachine
 from virtualization.models import VirtualMachine
 from . import serializers
 from . import serializers
 from .exceptions import MissingFilterException
 from .exceptions import MissingFilterException
@@ -119,12 +119,12 @@ class SiteViewSet(CustomFieldModelViewSet):
     queryset = Site.objects.prefetch_related(
     queryset = Site.objects.prefetch_related(
         'region', 'tenant', 'tags'
         'region', 'tenant', 'tags'
     ).annotate(
     ).annotate(
-        device_count=get_subquery(Device, 'site'),
-        rack_count=get_subquery(Rack, 'site'),
-        prefix_count=get_subquery(Prefix, 'site'),
-        vlan_count=get_subquery(VLAN, 'site'),
-        circuit_count=get_subquery(Circuit, 'terminations__site'),
-        virtualmachine_count=get_subquery(VirtualMachine, 'cluster__site')
+        device_count=count_related(Device, 'site'),
+        rack_count=count_related(Rack, 'site'),
+        prefix_count=count_related(Prefix, 'site'),
+        vlan_count=count_related(VLAN, 'site'),
+        circuit_count=count_related(Circuit, 'terminations__site'),
+        virtualmachine_count=count_related(VirtualMachine, 'cluster__site')
     )
     )
     serializer_class = serializers.SiteSerializer
     serializer_class = serializers.SiteSerializer
     filterset_class = filters.SiteFilterSet
     filterset_class = filters.SiteFilterSet
@@ -152,7 +152,7 @@ class RackGroupViewSet(ModelViewSet):
 
 
 class RackRoleViewSet(ModelViewSet):
 class RackRoleViewSet(ModelViewSet):
     queryset = RackRole.objects.annotate(
     queryset = RackRole.objects.annotate(
-        rack_count=get_subquery(Rack, 'role')
+        rack_count=count_related(Rack, 'role')
     )
     )
     serializer_class = serializers.RackRoleSerializer
     serializer_class = serializers.RackRoleSerializer
     filterset_class = filters.RackRoleFilterSet
     filterset_class = filters.RackRoleFilterSet
@@ -166,8 +166,8 @@ class RackViewSet(CustomFieldModelViewSet):
     queryset = Rack.objects.prefetch_related(
     queryset = Rack.objects.prefetch_related(
         'site', 'group__site', 'role', 'tenant', 'tags'
         'site', 'group__site', 'role', 'tenant', 'tags'
     ).annotate(
     ).annotate(
-        device_count=get_subquery(Device, 'rack'),
-        powerfeed_count=get_subquery(PowerFeed, 'rack')
+        device_count=count_related(Device, 'rack'),
+        powerfeed_count=count_related(PowerFeed, 'rack')
     )
     )
     serializer_class = serializers.RackSerializer
     serializer_class = serializers.RackSerializer
     filterset_class = filters.RackFilterSet
     filterset_class = filters.RackFilterSet
@@ -240,9 +240,9 @@ class RackReservationViewSet(ModelViewSet):
 
 
 class ManufacturerViewSet(ModelViewSet):
 class ManufacturerViewSet(ModelViewSet):
     queryset = Manufacturer.objects.annotate(
     queryset = Manufacturer.objects.annotate(
-        devicetype_count=get_subquery(DeviceType, 'manufacturer'),
-        inventoryitem_count=get_subquery(InventoryItem, 'manufacturer'),
-        platform_count=get_subquery(Platform, 'manufacturer')
+        devicetype_count=count_related(DeviceType, 'manufacturer'),
+        inventoryitem_count=count_related(InventoryItem, 'manufacturer'),
+        platform_count=count_related(Platform, 'manufacturer')
     )
     )
     serializer_class = serializers.ManufacturerSerializer
     serializer_class = serializers.ManufacturerSerializer
     filterset_class = filters.ManufacturerFilterSet
     filterset_class = filters.ManufacturerFilterSet
@@ -254,7 +254,7 @@ class ManufacturerViewSet(ModelViewSet):
 
 
 class DeviceTypeViewSet(CustomFieldModelViewSet):
 class DeviceTypeViewSet(CustomFieldModelViewSet):
     queryset = DeviceType.objects.prefetch_related('manufacturer', 'tags').annotate(
     queryset = DeviceType.objects.prefetch_related('manufacturer', 'tags').annotate(
-        device_count=get_subquery(Device, 'device_type')
+        device_count=count_related(Device, 'device_type')
     )
     )
     serializer_class = serializers.DeviceTypeSerializer
     serializer_class = serializers.DeviceTypeSerializer
     filterset_class = filters.DeviceTypeFilterSet
     filterset_class = filters.DeviceTypeFilterSet
@@ -318,8 +318,8 @@ class DeviceBayTemplateViewSet(ModelViewSet):
 
 
 class DeviceRoleViewSet(ModelViewSet):
 class DeviceRoleViewSet(ModelViewSet):
     queryset = DeviceRole.objects.annotate(
     queryset = DeviceRole.objects.annotate(
-        device_count=get_subquery(Device, 'device_role'),
-        virtualmachine_count=get_subquery(VirtualMachine, 'role')
+        device_count=count_related(Device, 'device_role'),
+        virtualmachine_count=count_related(VirtualMachine, 'role')
     )
     )
     serializer_class = serializers.DeviceRoleSerializer
     serializer_class = serializers.DeviceRoleSerializer
     filterset_class = filters.DeviceRoleFilterSet
     filterset_class = filters.DeviceRoleFilterSet
@@ -331,8 +331,8 @@ class DeviceRoleViewSet(ModelViewSet):
 
 
 class PlatformViewSet(ModelViewSet):
 class PlatformViewSet(ModelViewSet):
     queryset = Platform.objects.annotate(
     queryset = Platform.objects.annotate(
-        device_count=get_subquery(Device, 'platform'),
-        virtualmachine_count=get_subquery(VirtualMachine, 'platform')
+        device_count=count_related(Device, 'platform'),
+        virtualmachine_count=count_related(VirtualMachine, 'platform')
     )
     )
     serializer_class = serializers.PlatformSerializer
     serializer_class = serializers.PlatformSerializer
     filterset_class = filters.PlatformFilterSet
     filterset_class = filters.PlatformFilterSet
@@ -596,7 +596,7 @@ class CableViewSet(ModelViewSet):
 
 
 class VirtualChassisViewSet(ModelViewSet):
 class VirtualChassisViewSet(ModelViewSet):
     queryset = VirtualChassis.objects.prefetch_related('tags').annotate(
     queryset = VirtualChassis.objects.prefetch_related('tags').annotate(
-        member_count=get_subquery(Device, 'virtual_chassis')
+        member_count=count_related(Device, 'virtual_chassis')
     )
     )
     serializer_class = serializers.VirtualChassisSerializer
     serializer_class = serializers.VirtualChassisSerializer
     filterset_class = filters.VirtualChassisFilterSet
     filterset_class = filters.VirtualChassisFilterSet
@@ -610,7 +610,7 @@ class PowerPanelViewSet(ModelViewSet):
     queryset = PowerPanel.objects.prefetch_related(
     queryset = PowerPanel.objects.prefetch_related(
         'site', 'rack_group'
         'site', 'rack_group'
     ).annotate(
     ).annotate(
-        powerfeed_count=get_subquery(PowerFeed, 'power_panel')
+        powerfeed_count=count_related(PowerFeed, 'power_panel')
     )
     )
     serializer_class = serializers.PowerPanelSerializer
     serializer_class = serializers.PowerPanelSerializer
     filterset_class = filters.PowerPanelFilterSet
     filterset_class = filters.PowerPanelFilterSet

+ 18 - 18
netbox/dcim/views.py

@@ -20,7 +20,7 @@ from secrets.models import Secret
 from utilities.forms import ConfirmationForm
 from utilities.forms import ConfirmationForm
 from utilities.paginator import EnhancedPaginator, get_paginate_count
 from utilities.paginator import EnhancedPaginator, get_paginate_count
 from utilities.permissions import get_permission_for_model
 from utilities.permissions import get_permission_for_model
-from utilities.utils import csv_format, get_subquery
+from utilities.utils import csv_format, count_related
 from utilities.views import GetReturnURLMixin, ObjectPermissionRequiredMixin
 from utilities.views import GetReturnURLMixin, ObjectPermissionRequiredMixin
 from virtualization.models import VirtualMachine
 from virtualization.models import VirtualMachine
 from . import filters, forms, tables
 from . import filters, forms, tables
@@ -254,7 +254,7 @@ class RackGroupBulkDeleteView(generic.BulkDeleteView):
 
 
 class RackRoleListView(generic.ObjectListView):
 class RackRoleListView(generic.ObjectListView):
     queryset = RackRole.objects.annotate(
     queryset = RackRole.objects.annotate(
-        rack_count=get_subquery(Rack, 'role')
+        rack_count=count_related(Rack, 'role')
     )
     )
     table = tables.RackRoleTable
     table = tables.RackRoleTable
 
 
@@ -276,7 +276,7 @@ class RackRoleBulkImportView(generic.BulkImportView):
 
 
 class RackRoleBulkDeleteView(generic.BulkDeleteView):
 class RackRoleBulkDeleteView(generic.BulkDeleteView):
     queryset = RackRole.objects.annotate(
     queryset = RackRole.objects.annotate(
-        rack_count=get_subquery(Rack, 'role')
+        rack_count=count_related(Rack, 'role')
     )
     )
     table = tables.RackRoleTable
     table = tables.RackRoleTable
 
 
@@ -289,7 +289,7 @@ class RackListView(generic.ObjectListView):
     queryset = Rack.objects.prefetch_related(
     queryset = Rack.objects.prefetch_related(
         'site', 'group', 'tenant', 'role', 'devices__device_type'
         'site', 'group', 'tenant', 'role', 'devices__device_type'
     ).annotate(
     ).annotate(
-        device_count=get_subquery(Device, 'rack')
+        device_count=count_related(Device, 'rack')
     )
     )
     filterset = filters.RackFilterSet
     filterset = filters.RackFilterSet
     filterset_form = forms.RackFilterForm
     filterset_form = forms.RackFilterForm
@@ -470,9 +470,9 @@ class RackReservationBulkDeleteView(generic.BulkDeleteView):
 
 
 class ManufacturerListView(generic.ObjectListView):
 class ManufacturerListView(generic.ObjectListView):
     queryset = Manufacturer.objects.annotate(
     queryset = Manufacturer.objects.annotate(
-        devicetype_count=get_subquery(DeviceType, 'manufacturer'),
-        inventoryitem_count=get_subquery(InventoryItem, 'manufacturer'),
-        platform_count=get_subquery(Platform, 'manufacturer')
+        devicetype_count=count_related(DeviceType, 'manufacturer'),
+        inventoryitem_count=count_related(InventoryItem, 'manufacturer'),
+        platform_count=count_related(Platform, 'manufacturer')
     )
     )
     table = tables.ManufacturerTable
     table = tables.ManufacturerTable
 
 
@@ -494,7 +494,7 @@ class ManufacturerBulkImportView(generic.BulkImportView):
 
 
 class ManufacturerBulkDeleteView(generic.BulkDeleteView):
 class ManufacturerBulkDeleteView(generic.BulkDeleteView):
     queryset = Manufacturer.objects.annotate(
     queryset = Manufacturer.objects.annotate(
-        devicetype_count=get_subquery(DeviceType, 'manufacturer')
+        devicetype_count=count_related(DeviceType, 'manufacturer')
     )
     )
     table = tables.ManufacturerTable
     table = tables.ManufacturerTable
 
 
@@ -505,7 +505,7 @@ class ManufacturerBulkDeleteView(generic.BulkDeleteView):
 
 
 class DeviceTypeListView(generic.ObjectListView):
 class DeviceTypeListView(generic.ObjectListView):
     queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(
     queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(
-        instance_count=get_subquery(Device, 'device_type')
+        instance_count=count_related(Device, 'device_type')
     )
     )
     filterset = filters.DeviceTypeFilterSet
     filterset = filters.DeviceTypeFilterSet
     filterset_form = forms.DeviceTypeFilterForm
     filterset_form = forms.DeviceTypeFilterForm
@@ -612,7 +612,7 @@ class DeviceTypeImportView(generic.ObjectImportView):
 
 
 class DeviceTypeBulkEditView(generic.BulkEditView):
 class DeviceTypeBulkEditView(generic.BulkEditView):
     queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(
     queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(
-        instance_count=get_subquery(Device, 'device_type')
+        instance_count=count_related(Device, 'device_type')
     )
     )
     filterset = filters.DeviceTypeFilterSet
     filterset = filters.DeviceTypeFilterSet
     table = tables.DeviceTypeTable
     table = tables.DeviceTypeTable
@@ -621,7 +621,7 @@ class DeviceTypeBulkEditView(generic.BulkEditView):
 
 
 class DeviceTypeBulkDeleteView(generic.BulkDeleteView):
 class DeviceTypeBulkDeleteView(generic.BulkDeleteView):
     queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(
     queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(
-        instance_count=get_subquery(Device, 'device_type')
+        instance_count=count_related(Device, 'device_type')
     )
     )
     filterset = filters.DeviceTypeFilterSet
     filterset = filters.DeviceTypeFilterSet
     table = tables.DeviceTypeTable
     table = tables.DeviceTypeTable
@@ -913,8 +913,8 @@ class DeviceBayTemplateBulkDeleteView(generic.BulkDeleteView):
 
 
 class DeviceRoleListView(generic.ObjectListView):
 class DeviceRoleListView(generic.ObjectListView):
     queryset = DeviceRole.objects.annotate(
     queryset = DeviceRole.objects.annotate(
-        device_count=get_subquery(Device, 'device_role'),
-        vm_count=get_subquery(VirtualMachine, 'role')
+        device_count=count_related(Device, 'device_role'),
+        vm_count=count_related(VirtualMachine, 'role')
     )
     )
     table = tables.DeviceRoleTable
     table = tables.DeviceRoleTable
 
 
@@ -945,8 +945,8 @@ class DeviceRoleBulkDeleteView(generic.BulkDeleteView):
 
 
 class PlatformListView(generic.ObjectListView):
 class PlatformListView(generic.ObjectListView):
     queryset = Platform.objects.annotate(
     queryset = Platform.objects.annotate(
-        device_count=get_subquery(Device, 'platform'),
-        vm_count=get_subquery(VirtualMachine, 'platform')
+        device_count=count_related(Device, 'platform'),
+        vm_count=count_related(VirtualMachine, 'platform')
     )
     )
     table = tables.PlatformTable
     table = tables.PlatformTable
 
 
@@ -2335,7 +2335,7 @@ class InterfaceConnectionsListView(generic.ObjectListView):
 
 
 class VirtualChassisListView(generic.ObjectListView):
 class VirtualChassisListView(generic.ObjectListView):
     queryset = VirtualChassis.objects.prefetch_related('master').annotate(
     queryset = VirtualChassis.objects.prefetch_related('master').annotate(
-        member_count=get_subquery(Device, 'virtual_chassis')
+        member_count=count_related(Device, 'virtual_chassis')
     )
     )
     table = tables.VirtualChassisTable
     table = tables.VirtualChassisTable
     filterset = filters.VirtualChassisFilterSet
     filterset = filters.VirtualChassisFilterSet
@@ -2565,7 +2565,7 @@ class PowerPanelListView(generic.ObjectListView):
     queryset = PowerPanel.objects.prefetch_related(
     queryset = PowerPanel.objects.prefetch_related(
         'site', 'rack_group'
         'site', 'rack_group'
     ).annotate(
     ).annotate(
-        powerfeed_count=get_subquery(PowerFeed, 'power_panel')
+        powerfeed_count=count_related(PowerFeed, 'power_panel')
     )
     )
     filterset = filters.PowerPanelFilterSet
     filterset = filters.PowerPanelFilterSet
     filterset_form = forms.PowerPanelFilterForm
     filterset_form = forms.PowerPanelFilterForm
@@ -2615,7 +2615,7 @@ class PowerPanelBulkDeleteView(generic.BulkDeleteView):
     queryset = PowerPanel.objects.prefetch_related(
     queryset = PowerPanel.objects.prefetch_related(
         'site', 'rack_group'
         'site', 'rack_group'
     ).annotate(
     ).annotate(
-        powerfeed_count=get_subquery(PowerFeed, 'power_panel')
+        powerfeed_count=count_related(PowerFeed, 'power_panel')
     )
     )
     filterset = filters.PowerPanelFilterSet
     filterset = filters.PowerPanelFilterSet
     table = tables.PowerPanelTable
     table = tables.PowerPanelTable

+ 2 - 2
netbox/extras/api/views.py

@@ -21,7 +21,7 @@ from netbox.api.authentication import IsAuthenticatedOrLoginNotRequired
 from netbox.api.metadata import ContentTypeMetadata
 from netbox.api.metadata import ContentTypeMetadata
 from netbox.api.views import ModelViewSet
 from netbox.api.views import ModelViewSet
 from utilities.exceptions import RQWorkerNotRunningException
 from utilities.exceptions import RQWorkerNotRunningException
-from utilities.utils import copy_safe_request, get_subquery
+from utilities.utils import copy_safe_request, count_related
 from . import serializers
 from . import serializers
 
 
 
 
@@ -102,7 +102,7 @@ class ExportTemplateViewSet(ModelViewSet):
 
 
 class TagViewSet(ModelViewSet):
 class TagViewSet(ModelViewSet):
     queryset = Tag.objects.annotate(
     queryset = Tag.objects.annotate(
-        tagged_items=get_subquery(TaggedItem, 'tag')
+        tagged_items=count_related(TaggedItem, 'tag')
     )
     )
     serializer_class = serializers.TagSerializer
     serializer_class = serializers.TagSerializer
     filterset_class = filters.TagFilterSet
     filterset_class = filters.TagFilterSet

+ 4 - 4
netbox/extras/views.py

@@ -12,7 +12,7 @@ from rq import Worker
 from netbox.views import generic
 from netbox.views import generic
 from utilities.forms import ConfirmationForm
 from utilities.forms import ConfirmationForm
 from utilities.paginator import EnhancedPaginator, get_paginate_count
 from utilities.paginator import EnhancedPaginator, get_paginate_count
-from utilities.utils import copy_safe_request, get_subquery, shallow_compare_dict
+from utilities.utils import copy_safe_request, count_related, shallow_compare_dict
 from utilities.views import ContentTypePermissionRequiredMixin
 from utilities.views import ContentTypePermissionRequiredMixin
 from . import filters, forms, tables
 from . import filters, forms, tables
 from .choices import JobResultStatusChoices
 from .choices import JobResultStatusChoices
@@ -27,7 +27,7 @@ from .scripts import get_scripts, run_script
 
 
 class TagListView(generic.ObjectListView):
 class TagListView(generic.ObjectListView):
     queryset = Tag.objects.annotate(
     queryset = Tag.objects.annotate(
-        items=get_subquery(TaggedItem, 'tag')
+        items=count_related(TaggedItem, 'tag')
     )
     )
     filterset = filters.TagFilterSet
     filterset = filters.TagFilterSet
     filterset_form = forms.TagFilterForm
     filterset_form = forms.TagFilterForm
@@ -52,7 +52,7 @@ class TagBulkImportView(generic.BulkImportView):
 
 
 class TagBulkEditView(generic.BulkEditView):
 class TagBulkEditView(generic.BulkEditView):
     queryset = Tag.objects.annotate(
     queryset = Tag.objects.annotate(
-        items=get_subquery(TaggedItem, 'tag')
+        items=count_related(TaggedItem, 'tag')
     )
     )
     table = tables.TagTable
     table = tables.TagTable
     form = forms.TagBulkEditForm
     form = forms.TagBulkEditForm
@@ -60,7 +60,7 @@ class TagBulkEditView(generic.BulkEditView):
 
 
 class TagBulkDeleteView(generic.BulkDeleteView):
 class TagBulkDeleteView(generic.BulkDeleteView):
     queryset = Tag.objects.annotate(
     queryset = Tag.objects.annotate(
-        items=get_subquery(TaggedItem, 'tag')
+        items=count_related(TaggedItem, 'tag')
     )
     )
     table = tables.TagTable
     table = tables.TagTable
 
 

+ 8 - 8
netbox/ipam/api/views.py

@@ -12,7 +12,7 @@ from ipam import filters
 from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, RouteTarget, Service, VLAN, VLANGroup, VRF
 from ipam.models import Aggregate, IPAddress, Prefix, RIR, Role, RouteTarget, Service, VLAN, VLANGroup, VRF
 from netbox.api.views import ModelViewSet
 from netbox.api.views import ModelViewSet
 from utilities.constants import ADVISORY_LOCK_KEYS
 from utilities.constants import ADVISORY_LOCK_KEYS
-from utilities.utils import get_subquery
+from utilities.utils import count_related
 from . import serializers
 from . import serializers
 
 
 
 
@@ -32,8 +32,8 @@ class VRFViewSet(CustomFieldModelViewSet):
     queryset = VRF.objects.prefetch_related('tenant').prefetch_related(
     queryset = VRF.objects.prefetch_related('tenant').prefetch_related(
         'import_targets', 'export_targets', 'tags'
         'import_targets', 'export_targets', 'tags'
     ).annotate(
     ).annotate(
-        ipaddress_count=get_subquery(IPAddress, 'vrf'),
-        prefix_count=get_subquery(Prefix, 'vrf')
+        ipaddress_count=count_related(IPAddress, 'vrf'),
+        prefix_count=count_related(Prefix, 'vrf')
     )
     )
     serializer_class = serializers.VRFSerializer
     serializer_class = serializers.VRFSerializer
     filterset_class = filters.VRFFilterSet
     filterset_class = filters.VRFFilterSet
@@ -55,7 +55,7 @@ class RouteTargetViewSet(CustomFieldModelViewSet):
 
 
 class RIRViewSet(ModelViewSet):
 class RIRViewSet(ModelViewSet):
     queryset = RIR.objects.annotate(
     queryset = RIR.objects.annotate(
-        aggregate_count=get_subquery(Aggregate, 'rir')
+        aggregate_count=count_related(Aggregate, 'rir')
     )
     )
     serializer_class = serializers.RIRSerializer
     serializer_class = serializers.RIRSerializer
     filterset_class = filters.RIRFilterSet
     filterset_class = filters.RIRFilterSet
@@ -77,8 +77,8 @@ class AggregateViewSet(CustomFieldModelViewSet):
 
 
 class RoleViewSet(ModelViewSet):
 class RoleViewSet(ModelViewSet):
     queryset = Role.objects.annotate(
     queryset = Role.objects.annotate(
-        prefix_count=get_subquery(Prefix, 'role'),
-        vlan_count=get_subquery(VLAN, 'role')
+        prefix_count=count_related(Prefix, 'role'),
+        vlan_count=count_related(VLAN, 'role')
     )
     )
     serializer_class = serializers.RoleSerializer
     serializer_class = serializers.RoleSerializer
     filterset_class = filters.RoleFilterSet
     filterset_class = filters.RoleFilterSet
@@ -272,7 +272,7 @@ class IPAddressViewSet(CustomFieldModelViewSet):
 
 
 class VLANGroupViewSet(ModelViewSet):
 class VLANGroupViewSet(ModelViewSet):
     queryset = VLANGroup.objects.prefetch_related('site').annotate(
     queryset = VLANGroup.objects.prefetch_related('site').annotate(
-        vlan_count=get_subquery(VLAN, 'group')
+        vlan_count=count_related(VLAN, 'group')
     )
     )
     serializer_class = serializers.VLANGroupSerializer
     serializer_class = serializers.VLANGroupSerializer
     filterset_class = filters.VLANGroupFilterSet
     filterset_class = filters.VLANGroupFilterSet
@@ -286,7 +286,7 @@ class VLANViewSet(CustomFieldModelViewSet):
     queryset = VLAN.objects.prefetch_related(
     queryset = VLAN.objects.prefetch_related(
         'site', 'group', 'tenant', 'role', 'tags'
         'site', 'group', 'tenant', 'role', 'tags'
     ).annotate(
     ).annotate(
-        prefix_count=get_subquery(Prefix, 'vlan')
+        prefix_count=count_related(Prefix, 'vlan')
     )
     )
     serializer_class = serializers.VLANSerializer
     serializer_class = serializers.VLANSerializer
     filterset_class = filters.VLANFilterSet
     filterset_class = filters.VLANFilterSet

+ 7 - 7
netbox/ipam/views.py

@@ -6,7 +6,7 @@ from django_tables2 import RequestConfig
 from dcim.models import Device, Interface
 from dcim.models import Device, Interface
 from netbox.views import generic
 from netbox.views import generic
 from utilities.paginator import EnhancedPaginator, get_paginate_count
 from utilities.paginator import EnhancedPaginator, get_paginate_count
-from utilities.utils import get_subquery
+from utilities.utils import count_related
 from virtualization.models import VirtualMachine, VMInterface
 from virtualization.models import VirtualMachine, VMInterface
 from . import filters, forms, tables
 from . import filters, forms, tables
 from .constants import *
 from .constants import *
@@ -140,7 +140,7 @@ class RouteTargetBulkDeleteView(generic.BulkDeleteView):
 
 
 class RIRListView(generic.ObjectListView):
 class RIRListView(generic.ObjectListView):
     queryset = RIR.objects.annotate(
     queryset = RIR.objects.annotate(
-        aggregate_count=get_subquery(Aggregate, 'rir')
+        aggregate_count=count_related(Aggregate, 'rir')
     )
     )
     filterset = filters.RIRFilterSet
     filterset = filters.RIRFilterSet
     filterset_form = forms.RIRFilterForm
     filterset_form = forms.RIRFilterForm
@@ -165,7 +165,7 @@ class RIRBulkImportView(generic.BulkImportView):
 
 
 class RIRBulkDeleteView(generic.BulkDeleteView):
 class RIRBulkDeleteView(generic.BulkDeleteView):
     queryset = RIR.objects.annotate(
     queryset = RIR.objects.annotate(
-        aggregate_count=get_subquery(Aggregate, 'rir')
+        aggregate_count=count_related(Aggregate, 'rir')
     )
     )
     filterset = filters.RIRFilterSet
     filterset = filters.RIRFilterSet
     table = tables.RIRTable
     table = tables.RIRTable
@@ -277,8 +277,8 @@ class AggregateBulkDeleteView(generic.BulkDeleteView):
 
 
 class RoleListView(generic.ObjectListView):
 class RoleListView(generic.ObjectListView):
     queryset = Role.objects.annotate(
     queryset = Role.objects.annotate(
-        prefix_count=get_subquery(Prefix, 'role'),
-        vlan_count=get_subquery(VLAN, 'role')
+        prefix_count=count_related(Prefix, 'role'),
+        vlan_count=count_related(VLAN, 'role')
     )
     )
     table = tables.RoleTable
     table = tables.RoleTable
 
 
@@ -633,7 +633,7 @@ class IPAddressBulkDeleteView(generic.BulkDeleteView):
 
 
 class VLANGroupListView(generic.ObjectListView):
 class VLANGroupListView(generic.ObjectListView):
     queryset = VLANGroup.objects.prefetch_related('site').annotate(
     queryset = VLANGroup.objects.prefetch_related('site').annotate(
-        vlan_count=get_subquery(VLAN, 'group')
+        vlan_count=count_related(VLAN, 'group')
     )
     )
     filterset = filters.VLANGroupFilterSet
     filterset = filters.VLANGroupFilterSet
     filterset_form = forms.VLANGroupFilterForm
     filterset_form = forms.VLANGroupFilterForm
@@ -657,7 +657,7 @@ class VLANGroupBulkImportView(generic.BulkImportView):
 
 
 class VLANGroupBulkDeleteView(generic.BulkDeleteView):
 class VLANGroupBulkDeleteView(generic.BulkDeleteView):
     queryset = VLANGroup.objects.prefetch_related('site').annotate(
     queryset = VLANGroup.objects.prefetch_related('site').annotate(
-        vlan_count=get_subquery(VLAN, 'group')
+        vlan_count=count_related(VLAN, 'group')
     )
     )
     filterset = filters.VLANGroupFilterSet
     filterset = filters.VLANGroupFilterSet
     table = tables.VLANGroupTable
     table = tables.VLANGroupTable

+ 6 - 6
netbox/netbox/constants.py

@@ -23,7 +23,7 @@ from secrets.tables import SecretTable
 from tenancy.filters import TenantFilterSet
 from tenancy.filters import TenantFilterSet
 from tenancy.models import Tenant
 from tenancy.models import Tenant
 from tenancy.tables import TenantTable
 from tenancy.tables import TenantTable
-from utilities.utils import get_subquery
+from utilities.utils import count_related
 from virtualization.filters import ClusterFilterSet, VirtualMachineFilterSet
 from virtualization.filters import ClusterFilterSet, VirtualMachineFilterSet
 from virtualization.models import Cluster, VirtualMachine
 from virtualization.models import Cluster, VirtualMachine
 from virtualization.tables import ClusterTable, VirtualMachineDetailTable
 from virtualization.tables import ClusterTable, VirtualMachineDetailTable
@@ -33,7 +33,7 @@ SEARCH_TYPES = OrderedDict((
     # Circuits
     # Circuits
     ('provider', {
     ('provider', {
         'queryset': Provider.objects.annotate(
         'queryset': Provider.objects.annotate(
-            count_circuits=get_subquery(Circuit, 'provider')
+            count_circuits=count_related(Circuit, 'provider')
         ),
         ),
         'filterset': ProviderFilterSet,
         'filterset': ProviderFilterSet,
         'table': ProviderTable,
         'table': ProviderTable,
@@ -74,7 +74,7 @@ SEARCH_TYPES = OrderedDict((
     }),
     }),
     ('devicetype', {
     ('devicetype', {
         'queryset': DeviceType.objects.prefetch_related('manufacturer').annotate(
         'queryset': DeviceType.objects.prefetch_related('manufacturer').annotate(
-            instance_count=get_subquery(Device, 'device_type')
+            instance_count=count_related(Device, 'device_type')
         ),
         ),
         'filterset': DeviceTypeFilterSet,
         'filterset': DeviceTypeFilterSet,
         'table': DeviceTypeTable,
         'table': DeviceTypeTable,
@@ -90,7 +90,7 @@ SEARCH_TYPES = OrderedDict((
     }),
     }),
     ('virtualchassis', {
     ('virtualchassis', {
         'queryset': VirtualChassis.objects.prefetch_related('master').annotate(
         'queryset': VirtualChassis.objects.prefetch_related('master').annotate(
-            member_count=get_subquery(Device, 'virtual_chassis')
+            member_count=count_related(Device, 'virtual_chassis')
         ),
         ),
         'filterset': VirtualChassisFilterSet,
         'filterset': VirtualChassisFilterSet,
         'table': VirtualChassisTable,
         'table': VirtualChassisTable,
@@ -111,8 +111,8 @@ SEARCH_TYPES = OrderedDict((
     # Virtualization
     # Virtualization
     ('cluster', {
     ('cluster', {
         'queryset': Cluster.objects.prefetch_related('type', 'group').annotate(
         'queryset': Cluster.objects.prefetch_related('type', 'group').annotate(
-            device_count=get_subquery(Device, 'cluster'),
-            vm_count=get_subquery(VirtualMachine, 'cluster')
+            device_count=count_related(Device, 'cluster'),
+            vm_count=count_related(VirtualMachine, 'cluster')
         ),
         ),
         'filterset': ClusterFilterSet,
         'filterset': ClusterFilterSet,
         'table': ClusterTable,
         'table': ClusterTable,

+ 2 - 2
netbox/secrets/api/views.py

@@ -12,7 +12,7 @@ from netbox.api.views import ModelViewSet
 from secrets import filters
 from secrets import filters
 from secrets.exceptions import InvalidKey
 from secrets.exceptions import InvalidKey
 from secrets.models import Secret, SecretRole, SessionKey, UserKey
 from secrets.models import Secret, SecretRole, SessionKey, UserKey
-from utilities.utils import get_subquery
+from utilities.utils import count_related
 from . import serializers
 from . import serializers
 
 
 ERR_USERKEY_MISSING = "No UserKey found for the current user."
 ERR_USERKEY_MISSING = "No UserKey found for the current user."
@@ -35,7 +35,7 @@ class SecretsRootView(APIRootView):
 
 
 class SecretRoleViewSet(ModelViewSet):
 class SecretRoleViewSet(ModelViewSet):
     queryset = SecretRole.objects.annotate(
     queryset = SecretRole.objects.annotate(
-        secret_count=get_subquery(Secret, 'role')
+        secret_count=count_related(Secret, 'role')
     )
     )
     serializer_class = serializers.SecretRoleSerializer
     serializer_class = serializers.SecretRoleSerializer
     filterset_class = filters.SecretRoleFilterSet
     filterset_class = filters.SecretRoleFilterSet

+ 3 - 3
netbox/secrets/views.py

@@ -7,7 +7,7 @@ from django.utils.html import escape
 from django.utils.safestring import mark_safe
 from django.utils.safestring import mark_safe
 
 
 from netbox.views import generic
 from netbox.views import generic
-from utilities.utils import get_subquery
+from utilities.utils import count_related
 from . import filters, forms, tables
 from . import filters, forms, tables
 from .models import SecretRole, Secret, SessionKey, UserKey
 from .models import SecretRole, Secret, SessionKey, UserKey
 
 
@@ -28,7 +28,7 @@ def get_session_key(request):
 
 
 class SecretRoleListView(generic.ObjectListView):
 class SecretRoleListView(generic.ObjectListView):
     queryset = SecretRole.objects.annotate(
     queryset = SecretRole.objects.annotate(
-        secret_count=get_subquery(Secret, 'role')
+        secret_count=count_related(Secret, 'role')
     )
     )
     table = tables.SecretRoleTable
     table = tables.SecretRoleTable
 
 
@@ -50,7 +50,7 @@ class SecretRoleBulkImportView(generic.BulkImportView):
 
 
 class SecretRoleBulkDeleteView(generic.BulkDeleteView):
 class SecretRoleBulkDeleteView(generic.BulkDeleteView):
     queryset = SecretRole.objects.annotate(
     queryset = SecretRole.objects.annotate(
-        secret_count=get_subquery(Secret, 'role')
+        secret_count=count_related(Secret, 'role')
     )
     )
     table = tables.SecretRoleTable
     table = tables.SecretRoleTable
 
 

+ 10 - 10
netbox/tenancy/api/views.py

@@ -7,7 +7,7 @@ from ipam.models import IPAddress, Prefix, VLAN, VRF
 from netbox.api.views import ModelViewSet
 from netbox.api.views import ModelViewSet
 from tenancy import filters
 from tenancy import filters
 from tenancy.models import Tenant, TenantGroup
 from tenancy.models import Tenant, TenantGroup
-from utilities.utils import get_subquery
+from utilities.utils import count_related
 from virtualization.models import VirtualMachine
 from virtualization.models import VirtualMachine
 from . import serializers
 from . import serializers
 
 
@@ -44,15 +44,15 @@ class TenantViewSet(CustomFieldModelViewSet):
     queryset = Tenant.objects.prefetch_related(
     queryset = Tenant.objects.prefetch_related(
         'group', 'tags'
         'group', 'tags'
     ).annotate(
     ).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')
+        circuit_count=count_related(Circuit, 'tenant'),
+        device_count=count_related(Device, 'tenant'),
+        ipaddress_count=count_related(IPAddress, 'tenant'),
+        prefix_count=count_related(Prefix, 'tenant'),
+        rack_count=count_related(Rack, 'tenant'),
+        site_count=count_related(Site, 'tenant'),
+        virtualmachine_count=count_related(VirtualMachine, 'tenant'),
+        vlan_count=count_related(VLAN, 'tenant'),
+        vrf_count=count_related(VRF, 'tenant')
     )
     )
     serializer_class = serializers.TenantSerializer
     serializer_class = serializers.TenantSerializer
     filterset_class = filters.TenantFilterSet
     filterset_class = filters.TenantFilterSet

+ 1 - 1
netbox/utilities/utils.py

@@ -66,7 +66,7 @@ def dynamic_import(name):
     return mod
     return mod
 
 
 
 
-def get_subquery(model, field):
+def count_related(model, field):
     """
     """
     Return a Subquery suitable for annotating a child object count.
     Return a Subquery suitable for annotating a child object count.
     """
     """

+ 5 - 5
netbox/virtualization/api/views.py

@@ -2,7 +2,7 @@ from rest_framework.routers import APIRootView
 
 
 from dcim.models import Device
 from dcim.models import Device
 from extras.api.views import ConfigContextQuerySetMixin, CustomFieldModelViewSet, ModelViewSet
 from extras.api.views import ConfigContextQuerySetMixin, CustomFieldModelViewSet, ModelViewSet
-from utilities.utils import get_subquery
+from utilities.utils import count_related
 from virtualization import filters
 from virtualization import filters
 from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
 from virtualization.models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
 from . import serializers
 from . import serializers
@@ -22,7 +22,7 @@ class VirtualizationRootView(APIRootView):
 
 
 class ClusterTypeViewSet(ModelViewSet):
 class ClusterTypeViewSet(ModelViewSet):
     queryset = ClusterType.objects.annotate(
     queryset = ClusterType.objects.annotate(
-        cluster_count=get_subquery(Cluster, 'type')
+        cluster_count=count_related(Cluster, 'type')
     )
     )
     serializer_class = serializers.ClusterTypeSerializer
     serializer_class = serializers.ClusterTypeSerializer
     filterset_class = filters.ClusterTypeFilterSet
     filterset_class = filters.ClusterTypeFilterSet
@@ -30,7 +30,7 @@ class ClusterTypeViewSet(ModelViewSet):
 
 
 class ClusterGroupViewSet(ModelViewSet):
 class ClusterGroupViewSet(ModelViewSet):
     queryset = ClusterGroup.objects.annotate(
     queryset = ClusterGroup.objects.annotate(
-        cluster_count=get_subquery(Cluster, 'group')
+        cluster_count=count_related(Cluster, 'group')
     )
     )
     serializer_class = serializers.ClusterGroupSerializer
     serializer_class = serializers.ClusterGroupSerializer
     filterset_class = filters.ClusterGroupFilterSet
     filterset_class = filters.ClusterGroupFilterSet
@@ -40,8 +40,8 @@ class ClusterViewSet(CustomFieldModelViewSet):
     queryset = Cluster.objects.prefetch_related(
     queryset = Cluster.objects.prefetch_related(
         'type', 'group', 'tenant', 'site', 'tags'
         'type', 'group', 'tenant', 'site', 'tags'
     ).annotate(
     ).annotate(
-        device_count=get_subquery(Device, 'cluster'),
-        virtualmachine_count=get_subquery(VirtualMachine, 'cluster')
+        device_count=count_related(Device, 'cluster'),
+        virtualmachine_count=count_related(VirtualMachine, 'cluster')
     )
     )
     serializer_class = serializers.ClusterSerializer
     serializer_class = serializers.ClusterSerializer
     filterset_class = filters.ClusterFilterSet
     filterset_class = filters.ClusterFilterSet

+ 7 - 7
netbox/virtualization/views.py

@@ -11,7 +11,7 @@ from ipam.models import IPAddress, Service
 from ipam.tables import InterfaceIPAddressTable, InterfaceVLANTable
 from ipam.tables import InterfaceIPAddressTable, InterfaceVLANTable
 from netbox.views import generic
 from netbox.views import generic
 from secrets.models import Secret
 from secrets.models import Secret
-from utilities.utils import get_subquery
+from utilities.utils import count_related
 from . import filters, forms, tables
 from . import filters, forms, tables
 from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
 from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterface
 
 
@@ -22,7 +22,7 @@ from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterf
 
 
 class ClusterTypeListView(generic.ObjectListView):
 class ClusterTypeListView(generic.ObjectListView):
     queryset = ClusterType.objects.annotate(
     queryset = ClusterType.objects.annotate(
-        cluster_count=get_subquery(Cluster, 'type')
+        cluster_count=count_related(Cluster, 'type')
     )
     )
     table = tables.ClusterTypeTable
     table = tables.ClusterTypeTable
 
 
@@ -44,7 +44,7 @@ class ClusterTypeBulkImportView(generic.BulkImportView):
 
 
 class ClusterTypeBulkDeleteView(generic.BulkDeleteView):
 class ClusterTypeBulkDeleteView(generic.BulkDeleteView):
     queryset = ClusterType.objects.annotate(
     queryset = ClusterType.objects.annotate(
-        cluster_count=get_subquery(Cluster, 'type')
+        cluster_count=count_related(Cluster, 'type')
     )
     )
     table = tables.ClusterTypeTable
     table = tables.ClusterTypeTable
 
 
@@ -55,7 +55,7 @@ class ClusterTypeBulkDeleteView(generic.BulkDeleteView):
 
 
 class ClusterGroupListView(generic.ObjectListView):
 class ClusterGroupListView(generic.ObjectListView):
     queryset = ClusterGroup.objects.annotate(
     queryset = ClusterGroup.objects.annotate(
-        cluster_count=get_subquery(Cluster, 'group')
+        cluster_count=count_related(Cluster, 'group')
     )
     )
     table = tables.ClusterGroupTable
     table = tables.ClusterGroupTable
 
 
@@ -77,7 +77,7 @@ class ClusterGroupBulkImportView(generic.BulkImportView):
 
 
 class ClusterGroupBulkDeleteView(generic.BulkDeleteView):
 class ClusterGroupBulkDeleteView(generic.BulkDeleteView):
     queryset = ClusterGroup.objects.annotate(
     queryset = ClusterGroup.objects.annotate(
-        cluster_count=get_subquery(Cluster, 'group')
+        cluster_count=count_related(Cluster, 'group')
     )
     )
     table = tables.ClusterGroupTable
     table = tables.ClusterGroupTable
 
 
@@ -89,8 +89,8 @@ class ClusterGroupBulkDeleteView(generic.BulkDeleteView):
 class ClusterListView(generic.ObjectListView):
 class ClusterListView(generic.ObjectListView):
     permission_required = 'virtualization.view_cluster'
     permission_required = 'virtualization.view_cluster'
     queryset = Cluster.objects.annotate(
     queryset = Cluster.objects.annotate(
-        device_count=get_subquery(Device, 'cluster'),
-        vm_count=get_subquery(VirtualMachine, 'cluster')
+        device_count=count_related(Device, 'cluster'),
+        vm_count=count_related(VirtualMachine, 'cluster')
     )
     )
     table = tables.ClusterTable
     table = tables.ClusterTable
     filterset = filters.ClusterFilterSet
     filterset = filters.ClusterFilterSet