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

#4843: Use subqueries when counting multiple types of related objects

Jeremy Stretch 5 лет назад
Родитель
Сommit
a260019a7f
6 измененных файлов с 47 добавлено и 45 удалено
  1. 10 24
      netbox/dcim/tables.py
  2. 12 6
      netbox/dcim/views.py
  3. 3 7
      netbox/ipam/tables.py
  4. 5 1
      netbox/ipam/views.py
  5. 12 6
      netbox/virtualization/tables.py
  6. 5 1
      netbox/virtualization/views.py

+ 10 - 24
netbox/dcim/tables.py

@@ -103,20 +103,12 @@ DEVICEROLE_ACTIONS = """
 {% endif %}
 {% endif %}
 """
 """
 
 
-DEVICEROLE_DEVICE_COUNT = """
-<a href="{% url 'dcim:device_list' %}?role={{ record.slug }}">{{ value }}</a>
+DEVICE_COUNT = """
+<a href="{% url 'dcim:device_list' %}?role={{ record.slug }}">{{ value|default:0 }}</a>
 """
 """
 
 
-DEVICEROLE_VM_COUNT = """
-<a href="{% url 'virtualization:virtualmachine_list' %}?role={{ record.slug }}">{{ value }}</a>
-"""
-
-PLATFORM_DEVICE_COUNT = """
-<a href="{% url 'dcim:device_list' %}?platform={{ record.slug }}">{{ value }}</a>
-"""
-
-PLATFORM_VM_COUNT = """
-<a href="{% url 'virtualization:virtualmachine_list' %}?platform={{ record.slug }}">{{ value }}</a>
+VM_COUNT = """
+<a href="{% url 'virtualization:virtualmachine_list' %}?role={{ record.slug }}">{{ value|default:0 }}</a>
 """
 """
 
 
 PLATFORM_ACTIONS = """
 PLATFORM_ACTIONS = """
@@ -278,6 +270,7 @@ class RackGroupTable(BaseTable):
 
 
 class RackRoleTable(BaseTable):
 class RackRoleTable(BaseTable):
     pk = ToggleColumn()
     pk = ToggleColumn()
+    name = tables.Column(linkify=True)
     rack_count = tables.Column(verbose_name='Racks')
     rack_count = tables.Column(verbose_name='Racks')
     color = tables.TemplateColumn(COLOR_LABEL)
     color = tables.TemplateColumn(COLOR_LABEL)
     actions = tables.TemplateColumn(
     actions = tables.TemplateColumn(
@@ -704,21 +697,18 @@ class DeviceBayTemplateTable(BaseTable):
 class DeviceRoleTable(BaseTable):
 class DeviceRoleTable(BaseTable):
     pk = ToggleColumn()
     pk = ToggleColumn()
     device_count = tables.TemplateColumn(
     device_count = tables.TemplateColumn(
-        template_code=DEVICEROLE_DEVICE_COUNT,
-        accessor=Accessor('devices.count'),
-        orderable=False,
+        template_code=DEVICE_COUNT,
         verbose_name='Devices'
         verbose_name='Devices'
     )
     )
     vm_count = tables.TemplateColumn(
     vm_count = tables.TemplateColumn(
-        template_code=DEVICEROLE_VM_COUNT,
-        accessor=Accessor('virtual_machines.count'),
-        orderable=False,
+        template_code=VM_COUNT,
         verbose_name='VMs'
         verbose_name='VMs'
     )
     )
     color = tables.TemplateColumn(
     color = tables.TemplateColumn(
         template_code=COLOR_LABEL,
         template_code=COLOR_LABEL,
         verbose_name='Label'
         verbose_name='Label'
     )
     )
+    vm_role = BooleanColumn()
     actions = tables.TemplateColumn(
     actions = tables.TemplateColumn(
         template_code=DEVICEROLE_ACTIONS,
         template_code=DEVICEROLE_ACTIONS,
         attrs={'td': {'class': 'text-right noprint'}},
         attrs={'td': {'class': 'text-right noprint'}},
@@ -738,15 +728,11 @@ class DeviceRoleTable(BaseTable):
 class PlatformTable(BaseTable):
 class PlatformTable(BaseTable):
     pk = ToggleColumn()
     pk = ToggleColumn()
     device_count = tables.TemplateColumn(
     device_count = tables.TemplateColumn(
-        template_code=PLATFORM_DEVICE_COUNT,
-        accessor=Accessor('devices.count'),
-        orderable=False,
+        template_code=DEVICE_COUNT,
         verbose_name='Devices'
         verbose_name='Devices'
     )
     )
     vm_count = tables.TemplateColumn(
     vm_count = tables.TemplateColumn(
-        template_code=PLATFORM_VM_COUNT,
-        accessor=Accessor('virtual_machines.count'),
-        orderable=False,
+        template_code=VM_COUNT,
         verbose_name='VMs'
         verbose_name='VMs'
     )
     )
     actions = tables.TemplateColumn(
     actions = tables.TemplateColumn(

+ 12 - 6
netbox/dcim/views.py

@@ -23,7 +23,7 @@ from ipam.models import Prefix, VLAN
 from ipam.tables import InterfaceIPAddressTable, InterfaceVLANTable
 from ipam.tables import InterfaceIPAddressTable, InterfaceVLANTable
 from utilities.forms import ConfirmationForm
 from utilities.forms import ConfirmationForm
 from utilities.paginator import EnhancedPaginator
 from utilities.paginator import EnhancedPaginator
-from utilities.utils import csv_format
+from utilities.utils import csv_format, get_subquery
 from utilities.views import (
 from utilities.views import (
     BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, GetReturnURLMixin,
     BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, GetReturnURLMixin,
     ObjectImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
     ObjectImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
@@ -557,9 +557,9 @@ class RackReservationBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
 class ManufacturerListView(PermissionRequiredMixin, ObjectListView):
 class ManufacturerListView(PermissionRequiredMixin, ObjectListView):
     permission_required = 'dcim.view_manufacturer'
     permission_required = 'dcim.view_manufacturer'
     queryset = Manufacturer.objects.annotate(
     queryset = Manufacturer.objects.annotate(
-        devicetype_count=Count('device_types', distinct=True),
-        inventoryitem_count=Count('inventory_items', distinct=True),
-        platform_count=Count('platforms', distinct=True),
+        devicetype_count=get_subquery(DeviceType, 'manufacturer'),
+        inventoryitem_count=get_subquery(InventoryItem, 'manufacturer'),
+        platform_count=get_subquery(Platform, 'manufacturer')
     )
     )
     table = tables.ManufacturerTable
     table = tables.ManufacturerTable
 
 
@@ -1020,7 +1020,10 @@ class DeviceBayTemplateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
 
 
 class DeviceRoleListView(PermissionRequiredMixin, ObjectListView):
 class DeviceRoleListView(PermissionRequiredMixin, ObjectListView):
     permission_required = 'dcim.view_devicerole'
     permission_required = 'dcim.view_devicerole'
-    queryset = DeviceRole.objects.all()
+    queryset = DeviceRole.objects.annotate(
+        device_count=get_subquery(Device, 'device_role'),
+        vm_count=get_subquery(VirtualMachine, 'role')
+    )
     table = tables.DeviceRoleTable
     table = tables.DeviceRoleTable
 
 
 
 
@@ -1055,7 +1058,10 @@ class DeviceRoleBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
 
 
 class PlatformListView(PermissionRequiredMixin, ObjectListView):
 class PlatformListView(PermissionRequiredMixin, ObjectListView):
     permission_required = 'dcim.view_platform'
     permission_required = 'dcim.view_platform'
-    queryset = Platform.objects.all()
+    queryset = Platform.objects.annotate(
+        device_count=get_subquery(Device, 'device_role'),
+        vm_count=get_subquery(VirtualMachine, 'role')
+    )
     table = tables.PlatformTable
     table = tables.PlatformTable
 
 
 
 

+ 3 - 7
netbox/ipam/tables.py

@@ -40,11 +40,11 @@ UTILIZATION_GRAPH = """
 """
 """
 
 
 ROLE_PREFIX_COUNT = """
 ROLE_PREFIX_COUNT = """
-<a href="{% url 'ipam:prefix_list' %}?role={{ record.slug }}">{{ value }}</a>
+<a href="{% url 'ipam:prefix_list' %}?role={{ record.slug }}">{{ value|default:0 }}</a>
 """
 """
 
 
 ROLE_VLAN_COUNT = """
 ROLE_VLAN_COUNT = """
-<a href="{% url 'ipam:vlan_list' %}?role={{ record.slug }}">{{ value }}</a>
+<a href="{% url 'ipam:vlan_list' %}?role={{ record.slug }}">{{ value|default:0 }}</a>
 """
 """
 
 
 ROLE_ACTIONS = """
 ROLE_ACTIONS = """
@@ -319,15 +319,11 @@ class AggregateDetailTable(AggregateTable):
 class RoleTable(BaseTable):
 class RoleTable(BaseTable):
     pk = ToggleColumn()
     pk = ToggleColumn()
     prefix_count = tables.TemplateColumn(
     prefix_count = tables.TemplateColumn(
-        accessor=Accessor('prefixes.count'),
         template_code=ROLE_PREFIX_COUNT,
         template_code=ROLE_PREFIX_COUNT,
-        orderable=False,
         verbose_name='Prefixes'
         verbose_name='Prefixes'
     )
     )
     vlan_count = tables.TemplateColumn(
     vlan_count = tables.TemplateColumn(
-        accessor=Accessor('vlans.count'),
         template_code=ROLE_VLAN_COUNT,
         template_code=ROLE_VLAN_COUNT,
-        orderable=False,
         verbose_name='VLANs'
         verbose_name='VLANs'
     )
     )
     actions = tables.TemplateColumn(
     actions = tables.TemplateColumn(
@@ -524,7 +520,7 @@ class InterfaceIPAddressTable(BaseTable):
 
 
 class VLANGroupTable(BaseTable):
 class VLANGroupTable(BaseTable):
     pk = ToggleColumn()
     pk = ToggleColumn()
-    name = tables.LinkColumn()
+    name = tables.Column(linkify=True)
     site = tables.LinkColumn(
     site = tables.LinkColumn(
         viewname='dcim:site',
         viewname='dcim:site',
         args=[Accessor('site.slug')]
         args=[Accessor('site.slug')]

+ 5 - 1
netbox/ipam/views.py

@@ -9,6 +9,7 @@ from django_tables2 import RequestConfig
 
 
 from dcim.models import Device, Interface
 from dcim.models import Device, Interface
 from utilities.paginator import EnhancedPaginator
 from utilities.paginator import EnhancedPaginator
+from utilities.utils import get_subquery
 from utilities.views import (
 from utilities.views import (
     BulkCreateView, BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
     BulkCreateView, BulkDeleteView, BulkEditView, BulkImportView, ObjectDeleteView, ObjectEditView, ObjectListView,
 )
 )
@@ -407,7 +408,10 @@ class AggregateBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
 
 
 class RoleListView(PermissionRequiredMixin, ObjectListView):
 class RoleListView(PermissionRequiredMixin, ObjectListView):
     permission_required = 'ipam.view_role'
     permission_required = 'ipam.view_role'
-    queryset = Role.objects.all()
+    queryset = Role.objects.annotate(
+        prefix_count=get_subquery(Prefix, 'role'),
+        vlan_count=get_subquery(VLAN, 'role')
+    )
     table = tables.RoleTable
     table = tables.RoleTable
 
 
 
 

+ 12 - 6
netbox/virtualization/tables.py

@@ -34,6 +34,14 @@ VIRTUALMACHINE_PRIMARY_IP = """
 {{ record.primary_ip4.address.ip|default:"" }}
 {{ record.primary_ip4.address.ip|default:"" }}
 """
 """
 
 
+CLUSTER_DEVICE_COUNT = """
+<a href="{% url 'dcim:device_list' %}?cluster_id={{ record.pk }}">{{ value|default:0 }}</a>
+"""
+
+CLUSTER_VM_COUNT = """
+<a href="{% url 'virtualization:virtualmachine_list' %}?cluster_id={{ record.pk }}">{{ value|default:0 }}</a>
+"""
+
 
 
 #
 #
 # Cluster types
 # Cluster types
@@ -94,14 +102,12 @@ class ClusterTable(BaseTable):
         viewname='dcim:site',
         viewname='dcim:site',
         args=[Accessor('site.slug')]
         args=[Accessor('site.slug')]
     )
     )
-    device_count = tables.Column(
-        accessor=Accessor('devices.count'),
-        orderable=False,
+    device_count = tables.TemplateColumn(
+        template_code=CLUSTER_DEVICE_COUNT,
         verbose_name='Devices'
         verbose_name='Devices'
     )
     )
-    vm_count = tables.Column(
-        accessor=Accessor('virtual_machines.count'),
-        orderable=False,
+    vm_count = tables.TemplateColumn(
+        template_code=CLUSTER_VM_COUNT,
         verbose_name='VMs'
         verbose_name='VMs'
     )
     )
     tags = TagColumn(
     tags = TagColumn(

+ 5 - 1
netbox/virtualization/views.py

@@ -10,6 +10,7 @@ from dcim.models import Device, Interface
 from dcim.tables import DeviceTable
 from dcim.tables import DeviceTable
 from extras.views import ObjectConfigContextView
 from extras.views import ObjectConfigContextView
 from ipam.models import Service
 from ipam.models import Service
+from utilities.utils import get_subquery
 from utilities.views import (
 from utilities.views import (
     BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, ObjectDeleteView,
     BulkComponentCreateView, BulkDeleteView, BulkEditView, BulkImportView, ComponentCreateView, ObjectDeleteView,
     ObjectEditView, ObjectListView,
     ObjectEditView, ObjectListView,
@@ -94,7 +95,10 @@ class ClusterGroupBulkDeleteView(PermissionRequiredMixin, BulkDeleteView):
 
 
 class ClusterListView(PermissionRequiredMixin, ObjectListView):
 class ClusterListView(PermissionRequiredMixin, ObjectListView):
     permission_required = 'virtualization.view_cluster'
     permission_required = 'virtualization.view_cluster'
-    queryset = Cluster.objects.prefetch_related('type', 'group', 'site', 'tenant')
+    queryset = Cluster.objects.prefetch_related('type', 'group', 'site', 'tenant').annotate(
+        device_count=get_subquery(Device, 'cluster'),
+        vm_count=get_subquery(VirtualMachine, 'cluster')
+    )
     table = tables.ClusterTable
     table = tables.ClusterTable
     filterset = filters.ClusterFilterSet
     filterset = filters.ClusterFilterSet
     filterset_form = forms.ClusterFilterForm
     filterset_form = forms.ClusterFilterForm