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

Closes #4871: Specify ordering for querysets using annotate() to count related objects

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

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

@@ -19,7 +19,7 @@ from . import serializers
 class ProviderViewSet(CustomFieldModelViewSet):
     queryset = Provider.objects.prefetch_related('tags').annotate(
         circuit_count=Count('circuits')
-    )
+    ).order_by(*Provider._meta.ordering)
     serializer_class = serializers.ProviderSerializer
     filterset_class = filters.ProviderFilterSet
 
@@ -41,7 +41,7 @@ class ProviderViewSet(CustomFieldModelViewSet):
 class CircuitTypeViewSet(ModelViewSet):
     queryset = CircuitType.objects.annotate(
         circuit_count=Count('circuits')
-    )
+    ).order_by(*CircuitType._meta.ordering)
     serializer_class = serializers.CircuitTypeSerializer
     filterset_class = filters.CircuitTypeFilterSet
 

+ 5 - 5
netbox/circuits/views.py

@@ -21,7 +21,7 @@ from .models import Circuit, CircuitTermination, CircuitType, Provider
 #
 
 class ProviderListView(ObjectListView):
-    queryset = Provider.objects.annotate(count_circuits=Count('circuits'))
+    queryset = Provider.objects.annotate(count_circuits=Count('circuits')).order_by(*Provider._meta.ordering)
     filterset = filters.ProviderFilterSet
     filterset_form = forms.ProviderFilterForm
     table = tables.ProviderTable
@@ -73,14 +73,14 @@ class ProviderBulkImportView(BulkImportView):
 
 
 class ProviderBulkEditView(BulkEditView):
-    queryset = Provider.objects.annotate(count_circuits=Count('circuits'))
+    queryset = Provider.objects.annotate(count_circuits=Count('circuits')).order_by(*Provider._meta.ordering)
     filterset = filters.ProviderFilterSet
     table = tables.ProviderTable
     form = forms.ProviderBulkEditForm
 
 
 class ProviderBulkDeleteView(BulkDeleteView):
-    queryset = Provider.objects.annotate(count_circuits=Count('circuits'))
+    queryset = Provider.objects.annotate(count_circuits=Count('circuits')).order_by(*Provider._meta.ordering)
     filterset = filters.ProviderFilterSet
     table = tables.ProviderTable
 
@@ -90,7 +90,7 @@ class ProviderBulkDeleteView(BulkDeleteView):
 #
 
 class CircuitTypeListView(ObjectListView):
-    queryset = CircuitType.objects.annotate(circuit_count=Count('circuits'))
+    queryset = CircuitType.objects.annotate(circuit_count=Count('circuits')).order_by(*CircuitType._meta.ordering)
     table = tables.CircuitTypeTable
 
 
@@ -110,7 +110,7 @@ class CircuitTypeBulkImportView(BulkImportView):
 
 
 class CircuitTypeBulkDeleteView(BulkDeleteView):
-    queryset = CircuitType.objects.annotate(circuit_count=Count('circuits'))
+    queryset = CircuitType.objects.annotate(circuit_count=Count('circuits')).order_by(*CircuitType._meta.ordering)
     table = tables.CircuitTypeTable
 
 

+ 22 - 14
netbox/dcim/api/views.py

@@ -74,8 +74,12 @@ class CableTraceMixin(object):
 #
 
 class RegionViewSet(ModelViewSet):
-    queryset = Region.objects.annotate(
-        site_count=Count('sites')
+    queryset = Region.objects.add_related_count(
+        Region.objects.all(),
+        Site,
+        'region',
+        'site_count',
+        cumulative=True
     )
     serializer_class = serializers.RegionSerializer
     filterset_class = filters.RegionFilterSet
@@ -95,7 +99,7 @@ class SiteViewSet(CustomFieldModelViewSet):
         vlan_count=get_subquery(VLAN, 'site'),
         circuit_count=get_subquery(Circuit, 'terminations__site'),
         virtualmachine_count=get_subquery(VirtualMachine, 'cluster__site'),
-    )
+    ).order_by(*Site._meta.ordering)
     serializer_class = serializers.SiteSerializer
     filterset_class = filters.SiteFilterSet
 
@@ -115,9 +119,13 @@ class SiteViewSet(CustomFieldModelViewSet):
 #
 
 class RackGroupViewSet(ModelViewSet):
-    queryset = RackGroup.objects.prefetch_related('site').annotate(
-        rack_count=Count('racks')
-    )
+    queryset = RackGroup.objects.add_related_count(
+        RackGroup.objects.all(),
+        Rack,
+        'group',
+        'rack_count',
+        cumulative=True
+    ).prefetch_related('site')
     serializer_class = serializers.RackGroupSerializer
     filterset_class = filters.RackGroupFilterSet
 
@@ -129,7 +137,7 @@ class RackGroupViewSet(ModelViewSet):
 class RackRoleViewSet(ModelViewSet):
     queryset = RackRole.objects.annotate(
         rack_count=Count('racks')
-    )
+    ).order_by(*RackRole._meta.ordering)
     serializer_class = serializers.RackRoleSerializer
     filterset_class = filters.RackRoleFilterSet
 
@@ -144,7 +152,7 @@ class RackViewSet(CustomFieldModelViewSet):
     ).annotate(
         device_count=get_subquery(Device, 'rack'),
         powerfeed_count=get_subquery(PowerFeed, 'rack')
-    )
+    ).order_by(*Rack._meta.ordering)
     serializer_class = serializers.RackSerializer
     filterset_class = filters.RackFilterSet
 
@@ -217,7 +225,7 @@ class ManufacturerViewSet(ModelViewSet):
         devicetype_count=get_subquery(DeviceType, 'manufacturer'),
         inventoryitem_count=get_subquery(InventoryItem, 'manufacturer'),
         platform_count=get_subquery(Platform, 'manufacturer')
-    )
+    ).order_by(*Manufacturer._meta.ordering)
     serializer_class = serializers.ManufacturerSerializer
     filterset_class = filters.ManufacturerFilterSet
 
@@ -229,7 +237,7 @@ class ManufacturerViewSet(ModelViewSet):
 class DeviceTypeViewSet(CustomFieldModelViewSet):
     queryset = DeviceType.objects.prefetch_related('manufacturer', 'tags').annotate(
         device_count=Count('instances')
-    )
+    ).order_by(*DeviceType._meta.ordering)
     serializer_class = serializers.DeviceTypeSerializer
     filterset_class = filters.DeviceTypeFilterSet
 
@@ -294,7 +302,7 @@ class DeviceRoleViewSet(ModelViewSet):
     queryset = DeviceRole.objects.annotate(
         device_count=get_subquery(Device, 'device_role'),
         virtualmachine_count=get_subquery(VirtualMachine, 'role')
-    )
+    ).order_by(*DeviceRole._meta.ordering)
     serializer_class = serializers.DeviceRoleSerializer
     filterset_class = filters.DeviceRoleFilterSet
 
@@ -307,7 +315,7 @@ class PlatformViewSet(ModelViewSet):
     queryset = Platform.objects.annotate(
         device_count=get_subquery(Device, 'platform'),
         virtualmachine_count=get_subquery(VirtualMachine, 'platform')
-    )
+    ).order_by(*Platform._meta.ordering)
     serializer_class = serializers.PlatformSerializer
     filterset_class = filters.PlatformFilterSet
 
@@ -583,7 +591,7 @@ class CableViewSet(ModelViewSet):
 class VirtualChassisViewSet(ModelViewSet):
     queryset = VirtualChassis.objects.prefetch_related('tags').annotate(
         member_count=Count('members')
-    )
+    ).order_by(*VirtualChassis._meta.ordering)
     serializer_class = serializers.VirtualChassisSerializer
     filterset_class = filters.VirtualChassisFilterSet
 
@@ -597,7 +605,7 @@ class PowerPanelViewSet(ModelViewSet):
         'site', 'rack_group'
     ).annotate(
         powerfeed_count=Count('powerfeeds')
-    )
+    ).order_by(*PowerPanel._meta.ordering)
     serializer_class = serializers.PowerPanelSerializer
     filterset_class = filters.PowerPanelFilterSet
 

+ 35 - 13
netbox/dcim/views.py

@@ -133,7 +133,13 @@ class RegionBulkImportView(BulkImportView):
 
 
 class RegionBulkDeleteView(BulkDeleteView):
-    queryset = Region.objects.all()
+    queryset = Region.objects.add_related_count(
+        Region.objects.all(),
+        Site,
+        'region',
+        'site_count',
+        cumulative=True
+    )
     filterset = filters.RegionFilterSet
     table = tables.RegionTable
 
@@ -238,7 +244,13 @@ class RackGroupBulkImportView(BulkImportView):
 
 
 class RackGroupBulkDeleteView(BulkDeleteView):
-    queryset = RackGroup.objects.prefetch_related('site').annotate(rack_count=Count('racks'))
+    queryset = RackGroup.objects.add_related_count(
+        RackGroup.objects.all(),
+        Rack,
+        'group',
+        'rack_count',
+        cumulative=True
+    ).prefetch_related('site')
     filterset = filters.RackGroupFilterSet
     table = tables.RackGroupTable
 
@@ -248,7 +260,7 @@ class RackGroupBulkDeleteView(BulkDeleteView):
 #
 
 class RackRoleListView(ObjectListView):
-    queryset = RackRole.objects.annotate(rack_count=Count('racks'))
+    queryset = RackRole.objects.annotate(rack_count=Count('racks')).order_by(*RackRole._meta.ordering)
     table = tables.RackRoleTable
 
 
@@ -268,7 +280,7 @@ class RackRoleBulkImportView(BulkImportView):
 
 
 class RackRoleBulkDeleteView(BulkDeleteView):
-    queryset = RackRole.objects.annotate(rack_count=Count('racks'))
+    queryset = RackRole.objects.annotate(rack_count=Count('racks')).order_by(*RackRole._meta.ordering)
     table = tables.RackRoleTable
 
 
@@ -281,7 +293,7 @@ class RackListView(ObjectListView):
         'site', 'group', 'tenant', 'role', 'devices__device_type'
     ).annotate(
         device_count=Count('devices')
-    )
+    ).order_by(*Rack._meta.ordering)
     filterset = filters.RackFilterSet
     filterset_form = forms.RackFilterForm
     table = tables.RackDetailTable
@@ -465,7 +477,7 @@ class ManufacturerListView(ObjectListView):
         devicetype_count=Count('device_types', distinct=True),
         inventoryitem_count=Count('inventory_items', distinct=True),
         platform_count=Count('platforms', distinct=True),
-    )
+    ).order_by(*Manufacturer._meta.ordering)
     table = tables.ManufacturerTable
 
 
@@ -485,7 +497,9 @@ class ManufacturerBulkImportView(BulkImportView):
 
 
 class ManufacturerBulkDeleteView(BulkDeleteView):
-    queryset = Manufacturer.objects.annotate(devicetype_count=Count('device_types'))
+    queryset = Manufacturer.objects.annotate(
+        devicetype_count=Count('device_types')
+    ).order_by(*Manufacturer._meta.ordering)
     table = tables.ManufacturerTable
 
 
@@ -494,7 +508,9 @@ class ManufacturerBulkDeleteView(BulkDeleteView):
 #
 
 class DeviceTypeListView(ObjectListView):
-    queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(instance_count=Count('instances'))
+    queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(
+        instance_count=Count('instances')
+    ).order_by(*DeviceType._meta.ordering)
     filterset = filters.DeviceTypeFilterSet
     filterset_form = forms.DeviceTypeFilterForm
     table = tables.DeviceTypeTable
@@ -602,14 +618,18 @@ class DeviceTypeImportView(ObjectImportView):
 
 
 class DeviceTypeBulkEditView(BulkEditView):
-    queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(instance_count=Count('instances'))
+    queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(
+        instance_count=Count('instances')
+    ).order_by(*DeviceType._meta.ordering)
     filterset = filters.DeviceTypeFilterSet
     table = tables.DeviceTypeTable
     form = forms.DeviceTypeBulkEditForm
 
 
 class DeviceTypeBulkDeleteView(BulkDeleteView):
-    queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(instance_count=Count('instances'))
+    queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(
+        instance_count=Count('instances')
+    ).order_by(*DeviceType._meta.ordering)
     filterset = filters.DeviceTypeFilterSet
     table = tables.DeviceTypeTable
 
@@ -2152,7 +2172,9 @@ class InterfaceConnectionsListView(ObjectListView):
 #
 
 class VirtualChassisListView(ObjectListView):
-    queryset = VirtualChassis.objects.prefetch_related('master').annotate(member_count=Count('members'))
+    queryset = VirtualChassis.objects.prefetch_related('master').annotate(
+        member_count=Count('members')
+    ).order_by(*VirtualChassis._meta.ordering)
     table = tables.VirtualChassisTable
     filterset = filters.VirtualChassisFilterSet
     filterset_form = forms.VirtualChassisFilterForm
@@ -2385,7 +2407,7 @@ class PowerPanelListView(ObjectListView):
         'site', 'rack_group'
     ).annotate(
         powerfeed_count=Count('powerfeeds')
-    )
+    ).order_by(*PowerPanel._meta.ordering)
     filterset = filters.PowerPanelFilterSet
     filterset_form = forms.PowerPanelFilterForm
     table = tables.PowerPanelTable
@@ -2437,7 +2459,7 @@ class PowerPanelBulkDeleteView(BulkDeleteView):
         'site', 'rack_group'
     ).annotate(
         rack_count=Count('powerfeeds')
-    )
+    ).order_by(*PowerPanel._meta.ordering)
     filterset = filters.PowerPanelFilterSet
     table = tables.PowerPanelTable
 

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

@@ -24,7 +24,7 @@ class VRFViewSet(CustomFieldModelViewSet):
     queryset = VRF.objects.prefetch_related('tenant').prefetch_related('tags').annotate(
         ipaddress_count=get_subquery(IPAddress, 'vrf'),
         prefix_count=get_subquery(Prefix, 'vrf')
-    )
+    ).order_by(*VRF._meta.ordering)
     serializer_class = serializers.VRFSerializer
     filterset_class = filters.VRFFilterSet
 
@@ -36,7 +36,7 @@ class VRFViewSet(CustomFieldModelViewSet):
 class RIRViewSet(ModelViewSet):
     queryset = RIR.objects.annotate(
         aggregate_count=Count('aggregates')
-    )
+    ).order_by(*RIR._meta.ordering)
     serializer_class = serializers.RIRSerializer
     filterset_class = filters.RIRFilterSet
 
@@ -59,7 +59,7 @@ class RoleViewSet(ModelViewSet):
     queryset = Role.objects.annotate(
         prefix_count=get_subquery(Prefix, 'role'),
         vlan_count=get_subquery(VLAN, 'role')
-    )
+    ).order_by(*Role._meta.ordering)
     serializer_class = serializers.RoleSerializer
     filterset_class = filters.RoleFilterSet
 
@@ -246,7 +246,7 @@ class IPAddressViewSet(CustomFieldModelViewSet):
 class VLANGroupViewSet(ModelViewSet):
     queryset = VLANGroup.objects.prefetch_related('site').annotate(
         vlan_count=Count('vlans')
-    )
+    ).order_by(*VLANGroup._meta.ordering)
     serializer_class = serializers.VLANGroupSerializer
     filterset_class = filters.VLANGroupFilterSet
 
@@ -260,7 +260,7 @@ class VLANViewSet(CustomFieldModelViewSet):
         'site', 'group', 'tenant', 'role', 'tags'
     ).annotate(
         prefix_count=get_subquery(Prefix, 'vlan')
-    )
+    ).order_by(*VLAN._meta.ordering)
     serializer_class = serializers.VLANSerializer
     filterset_class = filters.VLANFilterSet
 

+ 9 - 5
netbox/ipam/views.py

@@ -78,7 +78,7 @@ class VRFBulkDeleteView(BulkDeleteView):
 #
 
 class RIRListView(ObjectListView):
-    queryset = RIR.objects.annotate(aggregate_count=Count('aggregates'))
+    queryset = RIR.objects.annotate(aggregate_count=Count('aggregates')).order_by(*RIR._meta.ordering)
     filterset = filters.RIRFilterSet
     filterset_form = forms.RIRFilterForm
     table = tables.RIRDetailTable
@@ -171,7 +171,7 @@ class RIRBulkImportView(BulkImportView):
 
 
 class RIRBulkDeleteView(BulkDeleteView):
-    queryset = RIR.objects.annotate(aggregate_count=Count('aggregates'))
+    queryset = RIR.objects.annotate(aggregate_count=Count('aggregates')).order_by(*RIR._meta.ordering)
     filterset = filters.RIRFilterSet
     table = tables.RIRTable
 
@@ -183,7 +183,7 @@ class RIRBulkDeleteView(BulkDeleteView):
 class AggregateListView(ObjectListView):
     queryset = Aggregate.objects.prefetch_related('rir').annotate(
         child_count=RawSQL('SELECT COUNT(*) FROM ipam_prefix WHERE ipam_prefix.prefix <<= ipam_aggregate.prefix', ())
-    )
+    ).order_by(*Aggregate._meta.ordering)
     filterset = filters.AggregateFilterSet
     filterset_form = forms.AggregateFilterForm
     table = tables.AggregateDetailTable
@@ -650,7 +650,9 @@ class IPAddressBulkDeleteView(BulkDeleteView):
 #
 
 class VLANGroupListView(ObjectListView):
-    queryset = VLANGroup.objects.prefetch_related('site').annotate(vlan_count=Count('vlans'))
+    queryset = VLANGroup.objects.prefetch_related('site').annotate(
+        vlan_count=Count('vlans')
+    ).order_by(*VLANGroup._meta.ordering)
     filterset = filters.VLANGroupFilterSet
     filterset_form = forms.VLANGroupFilterForm
     table = tables.VLANGroupTable
@@ -672,7 +674,9 @@ class VLANGroupBulkImportView(BulkImportView):
 
 
 class VLANGroupBulkDeleteView(BulkDeleteView):
-    queryset = VLANGroup.objects.prefetch_related('site').annotate(vlan_count=Count('vlans'))
+    queryset = VLANGroup.objects.prefetch_related('site').annotate(
+        vlan_count=Count('vlans')
+    ).order_by(*VLANGroup._meta.ordering)
     filterset = filters.VLANGroupFilterSet
     table = tables.VLANGroupTable
 

+ 12 - 4
netbox/netbox/views.py

@@ -46,7 +46,9 @@ SEARCH_MAX_RESULTS = 15
 SEARCH_TYPES = OrderedDict((
     # Circuits
     ('provider', {
-        'queryset': Provider.objects.annotate(count_circuits=Count('circuits')),
+        'queryset': Provider.objects.annotate(
+            count_circuits=Count('circuits')
+        ).order_by(*Provider._meta.ordering),
         'filterset': ProviderFilterSet,
         'table': ProviderTable,
         'url': 'circuits:provider_list',
@@ -73,13 +75,17 @@ SEARCH_TYPES = OrderedDict((
         'url': 'dcim:rack_list',
     }),
     ('rackgroup', {
-        'queryset': RackGroup.objects.prefetch_related('site').annotate(rack_count=Count('racks')),
+        'queryset': RackGroup.objects.prefetch_related('site').annotate(
+            rack_count=Count('racks')
+        ).order_by(*RackGroup._meta.ordering),
         'filterset': RackGroupFilterSet,
         'table': RackGroupTable,
         'url': 'dcim:rackgroup_list',
     }),
     ('devicetype', {
-        'queryset': DeviceType.objects.prefetch_related('manufacturer').annotate(instance_count=Count('instances')),
+        'queryset': DeviceType.objects.prefetch_related('manufacturer').annotate(
+            instance_count=Count('instances')
+        ).order_by(*DeviceType._meta.ordering),
         'filterset': DeviceTypeFilterSet,
         'table': DeviceTypeTable,
         'url': 'dcim:devicetype_list',
@@ -93,7 +99,9 @@ SEARCH_TYPES = OrderedDict((
         'url': 'dcim:device_list',
     }),
     ('virtualchassis', {
-        'queryset': VirtualChassis.objects.prefetch_related('master').annotate(member_count=Count('members')),
+        'queryset': VirtualChassis.objects.prefetch_related('master').annotate(
+            member_count=Count('members')
+        ).order_by(*VirtualChassis._meta.ordering),
         'filterset': VirtualChassisFilterSet,
         'table': VirtualChassisTable,
         'url': 'dcim:virtualchassis_list',

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

@@ -27,7 +27,7 @@ ERR_PRIVKEY_INVALID = "Invalid private key."
 class SecretRoleViewSet(ModelViewSet):
     queryset = SecretRole.objects.annotate(
         secret_count=Count('secrets')
-    )
+    ).order_by(*SecretRole._meta.ordering)
     serializer_class = serializers.SecretRoleSerializer
     filterset_class = filters.SecretRoleFilterSet
 

+ 2 - 2
netbox/secrets/views.py

@@ -29,7 +29,7 @@ def get_session_key(request):
 #
 
 class SecretRoleListView(ObjectListView):
-    queryset = SecretRole.objects.annotate(secret_count=Count('secrets'))
+    queryset = SecretRole.objects.annotate(secret_count=Count('secrets')).order_by(*SecretRole._meta.ordering)
     table = tables.SecretRoleTable
 
 
@@ -49,7 +49,7 @@ class SecretRoleBulkImportView(BulkImportView):
 
 
 class SecretRoleBulkDeleteView(BulkDeleteView):
-    queryset = SecretRole.objects.annotate(secret_count=Count('secrets'))
+    queryset = SecretRole.objects.annotate(secret_count=Count('secrets')).order_by(*SecretRole._meta.ordering)
     table = tables.SecretRoleTable
 
 

+ 6 - 2
netbox/tenancy/api/views.py

@@ -15,8 +15,12 @@ from . import serializers
 #
 
 class TenantGroupViewSet(ModelViewSet):
-    queryset = TenantGroup.objects.annotate(
-        tenant_count=get_subquery(Tenant, 'group')
+    queryset = TenantGroup.objects.add_related_count(
+        TenantGroup.objects.all(),
+        Tenant,
+        'group',
+        'tenant_count',
+        cumulative=True
     )
     serializer_class = serializers.TenantGroupSerializer
     filterset_class = filters.TenantGroupFilterSet

+ 7 - 1
netbox/tenancy/views.py

@@ -43,7 +43,13 @@ class TenantGroupBulkImportView(BulkImportView):
 
 
 class TenantGroupBulkDeleteView(BulkDeleteView):
-    queryset = TenantGroup.objects.annotate(tenant_count=Count('tenants'))
+    queryset = TenantGroup.objects.add_related_count(
+        TenantGroup.objects.all(),
+        Tenant,
+        'group',
+        'tenant_count',
+        cumulative=True
+    )
     table = tables.TenantGroupTable
 
 

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

@@ -22,7 +22,7 @@ from . import serializers
 class ClusterTypeViewSet(ModelViewSet):
     queryset = ClusterType.objects.annotate(
         cluster_count=Count('clusters')
-    )
+    ).order_by(*ClusterType._meta.ordering)
     serializer_class = serializers.ClusterTypeSerializer
     filterset_class = filters.ClusterTypeFilterSet
 
@@ -30,7 +30,7 @@ class ClusterTypeViewSet(ModelViewSet):
 class ClusterGroupViewSet(ModelViewSet):
     queryset = ClusterGroup.objects.annotate(
         cluster_count=Count('clusters')
-    )
+    ).order_by(*ClusterGroup._meta.ordering)
     serializer_class = serializers.ClusterGroupSerializer
     filterset_class = filters.ClusterGroupFilterSet
 
@@ -41,7 +41,7 @@ class ClusterViewSet(CustomFieldModelViewSet):
     ).annotate(
         device_count=get_subquery(Device, 'cluster'),
         virtualmachine_count=get_subquery(VirtualMachine, 'cluster')
-    )
+    ).order_by(*Cluster._meta.ordering)
     serializer_class = serializers.ClusterSerializer
     filterset_class = filters.ClusterFilterSet
 

+ 4 - 4
netbox/virtualization/views.py

@@ -22,7 +22,7 @@ from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterf
 #
 
 class ClusterTypeListView(ObjectListView):
-    queryset = ClusterType.objects.annotate(cluster_count=Count('clusters'))
+    queryset = ClusterType.objects.annotate(cluster_count=Count('clusters')).order_by(*ClusterType._meta.ordering)
     table = tables.ClusterTypeTable
 
 
@@ -42,7 +42,7 @@ class ClusterTypeBulkImportView(BulkImportView):
 
 
 class ClusterTypeBulkDeleteView(BulkDeleteView):
-    queryset = ClusterType.objects.annotate(cluster_count=Count('clusters'))
+    queryset = ClusterType.objects.annotate(cluster_count=Count('clusters')).order_by(*ClusterType._meta.ordering)
     table = tables.ClusterTypeTable
 
 
@@ -51,7 +51,7 @@ class ClusterTypeBulkDeleteView(BulkDeleteView):
 #
 
 class ClusterGroupListView(ObjectListView):
-    queryset = ClusterGroup.objects.annotate(cluster_count=Count('clusters'))
+    queryset = ClusterGroup.objects.annotate(cluster_count=Count('clusters')).order_by(*ClusterGroup._meta.ordering)
     table = tables.ClusterGroupTable
 
 
@@ -71,7 +71,7 @@ class ClusterGroupBulkImportView(BulkImportView):
 
 
 class ClusterGroupBulkDeleteView(BulkDeleteView):
-    queryset = ClusterGroup.objects.annotate(cluster_count=Count('clusters'))
+    queryset = ClusterGroup.objects.annotate(cluster_count=Count('clusters')).order_by(*ClusterGroup._meta.ordering)
     table = tables.ClusterGroupTable