1
0
mirror of https://github.com/netbox-community/netbox.git synced 2024-05-10 07:54:54 +00:00

Closes #4865: Replace all Count() annotations with subqueries (#5385)

* Convert circuits to use subqueries

* Convert dcim to use subqueries

* Convert extras to use subqueries

* Convert ipam to use subqueries

* Convert secrets to use subqueries

* Convert virtualization to use subqueries

* Update global search view to use subqueries where appropriate

* Remove extraneous order_by() calls
This commit is contained in:
Jeremy Stretch
2020-11-25 15:49:18 -05:00
committed by GitHub
parent 77bbe5730b
commit f55e966c8f
13 changed files with 134 additions and 103 deletions

View File

@ -1,4 +1,4 @@
from django.db.models import Count, Prefetch
from django.db.models import Prefetch
from django.shortcuts import get_object_or_404
from rest_framework.decorators import action
from rest_framework.response import Response
@ -10,6 +10,7 @@ from extras.api.serializers import RenderedGraphSerializer
from extras.api.views import CustomFieldModelViewSet
from extras.models import Graph
from utilities.api import ModelViewSet
from utilities.utils import get_subquery
from . import serializers
@ -27,8 +28,8 @@ class CircuitsRootView(APIRootView):
class ProviderViewSet(CustomFieldModelViewSet):
queryset = Provider.objects.prefetch_related('tags').annotate(
circuit_count=Count('circuits')
).order_by(*Provider._meta.ordering)
circuit_count=get_subquery(Circuit, 'provider')
)
serializer_class = serializers.ProviderSerializer
filterset_class = filters.ProviderFilterSet
@ -49,8 +50,8 @@ class ProviderViewSet(CustomFieldModelViewSet):
class CircuitTypeViewSet(ModelViewSet):
queryset = CircuitType.objects.annotate(
circuit_count=Count('circuits')
).order_by(*CircuitType._meta.ordering)
circuit_count=get_subquery(Circuit, 'type')
)
serializer_class = serializers.CircuitTypeSerializer
filterset_class = filters.CircuitTypeFilterSet

View File

@ -1,12 +1,12 @@
from django.contrib import messages
from django.db import transaction
from django.db.models import Count
from django.shortcuts import get_object_or_404, redirect, render
from django_tables2 import RequestConfig
from extras.models import Graph
from utilities.forms import ConfirmationForm
from utilities.paginator import EnhancedPaginator, get_paginate_count
from utilities.utils import get_subquery
from utilities.views import (
BulkDeleteView, BulkEditView, BulkImportView, ObjectView, ObjectDeleteView, ObjectEditView, ObjectListView,
)
@ -20,7 +20,9 @@ from .models import Circuit, CircuitTermination, CircuitType, Provider
#
class ProviderListView(ObjectListView):
queryset = Provider.objects.annotate(count_circuits=Count('circuits')).order_by(*Provider._meta.ordering)
queryset = Provider.objects.annotate(
count_circuits=get_subquery(Circuit, 'provider')
)
filterset = filters.ProviderFilterSet
filterset_form = forms.ProviderFilterForm
table = tables.ProviderTable
@ -72,14 +74,18 @@ class ProviderBulkImportView(BulkImportView):
class ProviderBulkEditView(BulkEditView):
queryset = Provider.objects.annotate(count_circuits=Count('circuits')).order_by(*Provider._meta.ordering)
queryset = Provider.objects.annotate(
count_circuits=get_subquery(Circuit, 'provider')
)
filterset = filters.ProviderFilterSet
table = tables.ProviderTable
form = forms.ProviderBulkEditForm
class ProviderBulkDeleteView(BulkDeleteView):
queryset = Provider.objects.annotate(count_circuits=Count('circuits')).order_by(*Provider._meta.ordering)
queryset = Provider.objects.annotate(
count_circuits=get_subquery(Circuit, 'provider')
)
filterset = filters.ProviderFilterSet
table = tables.ProviderTable
@ -89,7 +95,9 @@ class ProviderBulkDeleteView(BulkDeleteView):
#
class CircuitTypeListView(ObjectListView):
queryset = CircuitType.objects.annotate(circuit_count=Count('circuits')).order_by(*CircuitType._meta.ordering)
queryset = CircuitType.objects.annotate(
circuit_count=get_subquery(Circuit, 'type')
)
table = tables.CircuitTypeTable
@ -109,7 +117,9 @@ class CircuitTypeBulkImportView(BulkImportView):
class CircuitTypeBulkDeleteView(BulkDeleteView):
queryset = CircuitType.objects.annotate(circuit_count=Count('circuits')).order_by(*CircuitType._meta.ordering)
queryset = CircuitType.objects.annotate(
circuit_count=get_subquery(Circuit, 'type')
)
table = tables.CircuitTypeTable

View File

@ -2,7 +2,7 @@ import socket
from collections import OrderedDict
from django.conf import settings
from django.db.models import Count, F
from django.db.models import F
from django.http import HttpResponseForbidden, HttpResponse
from django.shortcuts import get_object_or_404
from drf_yasg import openapi
@ -109,7 +109,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
@ -146,8 +146,8 @@ class RackGroupViewSet(ModelViewSet):
class RackRoleViewSet(ModelViewSet):
queryset = RackRole.objects.annotate(
rack_count=Count('racks')
).order_by(*RackRole._meta.ordering)
rack_count=get_subquery(Rack, 'role')
)
serializer_class = serializers.RackRoleSerializer
filterset_class = filters.RackRoleFilterSet
@ -162,7 +162,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
@ -237,7 +237,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
@ -248,8 +248,8 @@ class ManufacturerViewSet(ModelViewSet):
class DeviceTypeViewSet(CustomFieldModelViewSet):
queryset = DeviceType.objects.prefetch_related('manufacturer', 'tags').annotate(
device_count=Count('instances')
).order_by(*DeviceType._meta.ordering)
device_count=get_subquery(Device, 'device_type')
)
serializer_class = serializers.DeviceTypeSerializer
filterset_class = filters.DeviceTypeFilterSet
@ -314,7 +314,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
@ -327,7 +327,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
@ -619,8 +619,8 @@ class CableViewSet(ModelViewSet):
class VirtualChassisViewSet(ModelViewSet):
queryset = VirtualChassis.objects.prefetch_related('tags').annotate(
member_count=Count('members', distinct=True)
).order_by(*VirtualChassis._meta.ordering)
member_count=get_subquery(Device, 'virtual_chassis')
)
serializer_class = serializers.VirtualChassisSerializer
filterset_class = filters.VirtualChassisFilterSet
@ -633,8 +633,8 @@ class PowerPanelViewSet(ModelViewSet):
queryset = PowerPanel.objects.prefetch_related(
'site', 'rack_group'
).annotate(
powerfeed_count=Count('powerfeeds')
).order_by(*PowerPanel._meta.ordering)
powerfeed_count=get_subquery(PowerFeed, 'power_panel')
)
serializer_class = serializers.PowerPanelSerializer
filterset_class = filters.PowerPanelFilterSet

View File

@ -4,7 +4,7 @@ from django.contrib import messages
from django.contrib.contenttypes.models import ContentType
from django.core.paginator import EmptyPage, PageNotAnInteger
from django.db import transaction
from django.db.models import Count, F, Prefetch
from django.db.models import F, Prefetch
from django.forms import ModelMultipleChoiceField, MultipleHiddenInput, modelformset_factory
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
@ -263,7 +263,9 @@ class RackGroupBulkDeleteView(BulkDeleteView):
#
class RackRoleListView(ObjectListView):
queryset = RackRole.objects.annotate(rack_count=Count('racks')).order_by(*RackRole._meta.ordering)
queryset = RackRole.objects.annotate(
rack_count=get_subquery(Rack, 'role')
)
table = tables.RackRoleTable
@ -283,7 +285,9 @@ class RackRoleBulkImportView(BulkImportView):
class RackRoleBulkDeleteView(BulkDeleteView):
queryset = RackRole.objects.annotate(rack_count=Count('racks')).order_by(*RackRole._meta.ordering)
queryset = RackRole.objects.annotate(
rack_count=get_subquery(Rack, 'role')
)
table = tables.RackRoleTable
@ -295,8 +299,8 @@ class RackListView(ObjectListView):
queryset = Rack.objects.prefetch_related(
'site', 'group', 'tenant', 'role', 'devices__device_type'
).annotate(
device_count=Count('devices')
).order_by(*Rack._meta.ordering)
device_count=get_subquery(Device, 'rack')
)
filterset = filters.RackFilterSet
filterset_form = forms.RackFilterForm
table = tables.RackDetailTable
@ -507,8 +511,8 @@ class ManufacturerBulkImportView(BulkImportView):
class ManufacturerBulkDeleteView(BulkDeleteView):
queryset = Manufacturer.objects.annotate(
devicetype_count=Count('device_types')
).order_by(*Manufacturer._meta.ordering)
devicetype_count=get_subquery(DeviceType, 'manufacturer')
)
table = tables.ManufacturerTable
@ -518,8 +522,8 @@ class ManufacturerBulkDeleteView(BulkDeleteView):
class DeviceTypeListView(ObjectListView):
queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(
instance_count=Count('instances')
).order_by(*DeviceType._meta.ordering)
instance_count=get_subquery(Device, 'device_type')
)
filterset = filters.DeviceTypeFilterSet
filterset_form = forms.DeviceTypeFilterForm
table = tables.DeviceTypeTable
@ -628,8 +632,8 @@ class DeviceTypeImportView(ObjectImportView):
class DeviceTypeBulkEditView(BulkEditView):
queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(
instance_count=Count('instances')
).order_by(*DeviceType._meta.ordering)
instance_count=get_subquery(Device, 'device_type')
)
filterset = filters.DeviceTypeFilterSet
table = tables.DeviceTypeTable
form = forms.DeviceTypeBulkEditForm
@ -637,8 +641,8 @@ class DeviceTypeBulkEditView(BulkEditView):
class DeviceTypeBulkDeleteView(BulkDeleteView):
queryset = DeviceType.objects.prefetch_related('manufacturer').annotate(
instance_count=Count('instances')
).order_by(*DeviceType._meta.ordering)
instance_count=get_subquery(Device, 'device_type')
)
filterset = filters.DeviceTypeFilterSet
table = tables.DeviceTypeTable
@ -2198,8 +2202,8 @@ class InterfaceConnectionsListView(ObjectListView):
class VirtualChassisListView(ObjectListView):
queryset = VirtualChassis.objects.prefetch_related('master').annotate(
member_count=Count('members', distinct=True)
).order_by(*VirtualChassis._meta.ordering)
member_count=get_subquery(Device, 'virtual_chassis')
)
table = tables.VirtualChassisTable
filterset = filters.VirtualChassisFilterSet
filterset_form = forms.VirtualChassisFilterForm
@ -2430,8 +2434,8 @@ class PowerPanelListView(ObjectListView):
queryset = PowerPanel.objects.prefetch_related(
'site', 'rack_group'
).annotate(
powerfeed_count=Count('powerfeeds')
).order_by(*PowerPanel._meta.ordering)
powerfeed_count=get_subquery(PowerFeed, 'power_panel')
)
filterset = filters.PowerPanelFilterSet
filterset_form = forms.PowerPanelFilterForm
table = tables.PowerPanelTable
@ -2482,8 +2486,8 @@ class PowerPanelBulkDeleteView(BulkDeleteView):
queryset = PowerPanel.objects.prefetch_related(
'site', 'rack_group'
).annotate(
rack_count=Count('powerfeeds')
).order_by(*PowerPanel._meta.ordering)
powerfeed_count=get_subquery(PowerFeed, 'power_panel')
)
filterset = filters.PowerPanelFilterSet
table = tables.PowerPanelTable

View File

@ -1,7 +1,6 @@
from collections import OrderedDict
from django.contrib.contenttypes.models import ContentType
from django.db.models import Count
from django.http import Http404
from django_rq.queues import get_connection
from rest_framework import status
@ -15,14 +14,14 @@ from rq import Worker
from extras import filters
from extras.choices import JobResultStatusChoices
from extras.models import (
ConfigContext, CustomFieldChoice, ExportTemplate, Graph, ImageAttachment, ObjectChange, JobResult, Tag,
ConfigContext, CustomFieldChoice, ExportTemplate, Graph, ImageAttachment, ObjectChange, JobResult, Tag, TaggedItem,
)
from extras.reports import get_report, get_reports, run_report
from extras.scripts import get_script, get_scripts, run_script
from utilities.api import IsAuthenticatedOrLoginNotRequired, ModelViewSet
from utilities.exceptions import RQWorkerNotRunningException
from utilities.metadata import ContentTypeMetadata
from utilities.utils import copy_safe_request
from utilities.utils import copy_safe_request, get_subquery
from . import serializers
@ -149,8 +148,8 @@ class ExportTemplateViewSet(ModelViewSet):
class TagViewSet(ModelViewSet):
queryset = Tag.objects.annotate(
tagged_items=Count('extras_taggeditem_items')
).order_by(*Tag._meta.ordering)
tagged_items=get_subquery(TaggedItem, 'tag')
)
serializer_class = serializers.TagSerializer
filterset_class = filters.TagFilterSet

View File

@ -1,7 +1,7 @@
from django import template
from django.contrib import messages
from django.contrib.contenttypes.models import ContentType
from django.db.models import Count, Prefetch, Q
from django.db.models import Prefetch, Q
from django.http import Http404, HttpResponseForbidden
from django.shortcuts import get_object_or_404, redirect, render
from django.views.generic import View
@ -13,7 +13,7 @@ from dcim.models import DeviceRole, Platform, Region, Site
from tenancy.models import Tenant, TenantGroup
from utilities.forms import ConfirmationForm
from utilities.paginator import EnhancedPaginator, get_paginate_count
from utilities.utils import copy_safe_request, shallow_compare_dict
from utilities.utils import copy_safe_request, get_subquery, shallow_compare_dict
from utilities.views import (
BulkDeleteView, BulkEditView, BulkImportView, ObjectView, ObjectDeleteView, ObjectEditView, ObjectListView,
ContentTypePermissionRequiredMixin,
@ -21,7 +21,7 @@ from utilities.views import (
from virtualization.models import Cluster, ClusterGroup
from . import filters, forms, tables
from .choices import JobResultStatusChoices
from .models import ConfigContext, ImageAttachment, ObjectChange, JobResult, Tag
from .models import ConfigContext, ImageAttachment, ObjectChange, JobResult, Tag, TaggedItem
from .reports import get_report, get_reports, run_report
from .scripts import get_scripts, run_script
@ -32,8 +32,8 @@ from .scripts import get_scripts, run_script
class TagListView(ObjectListView):
queryset = Tag.objects.annotate(
items=Count('extras_taggeditem_items')
).order_by(*Tag._meta.ordering)
items=get_subquery(TaggedItem, 'tag')
)
filterset = filters.TagFilterSet
filterset_form = forms.TagFilterForm
table = tables.TagTable
@ -57,16 +57,16 @@ class TagBulkImportView(BulkImportView):
class TagBulkEditView(BulkEditView):
queryset = Tag.objects.annotate(
items=Count('extras_taggeditem_items')
).order_by(*Tag._meta.ordering)
items=get_subquery(TaggedItem, 'tag')
)
table = tables.TagTable
form = forms.TagBulkEditForm
class TagBulkDeleteView(BulkDeleteView):
queryset = Tag.objects.annotate(
items=Count('extras_taggeditem_items')
).order_by(*Tag._meta.ordering)
items=get_subquery(TaggedItem, 'tag')
)
table = tables.TagTable

View File

@ -1,5 +1,4 @@
from django.conf import settings
from django.db.models import Count
from django.shortcuts import get_object_or_404
from django_pglocks import advisory_lock
from drf_yasg.utils import swagger_auto_schema
@ -33,7 +32,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
@ -44,8 +43,8 @@ class VRFViewSet(CustomFieldModelViewSet):
class RIRViewSet(ModelViewSet):
queryset = RIR.objects.annotate(
aggregate_count=Count('aggregates')
).order_by(*RIR._meta.ordering)
aggregate_count=get_subquery(Aggregate, 'rir')
)
serializer_class = serializers.RIRSerializer
filterset_class = filters.RIRFilterSet
@ -68,7 +67,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
@ -80,7 +79,7 @@ class RoleViewSet(ModelViewSet):
class PrefixViewSet(CustomFieldModelViewSet):
queryset = Prefix.objects.prefetch_related(
'site', 'vrf__tenant', 'tenant', 'vlan', 'role', 'tags'
).order_by(*Prefix._meta.ordering)
)
serializer_class = serializers.PrefixSerializer
filterset_class = filters.PrefixFilterSet
@ -250,7 +249,7 @@ class PrefixViewSet(CustomFieldModelViewSet):
class IPAddressViewSet(CustomFieldModelViewSet):
queryset = IPAddress.objects.prefetch_related(
'vrf__tenant', 'tenant', 'nat_inside', 'nat_outside', 'tags', 'assigned_object'
).order_by(*IPAddress._meta.ordering)
)
serializer_class = serializers.IPAddressSerializer
filterset_class = filters.IPAddressFilterSet
@ -261,8 +260,8 @@ class IPAddressViewSet(CustomFieldModelViewSet):
class VLANGroupViewSet(ModelViewSet):
queryset = VLANGroup.objects.prefetch_related('site').annotate(
vlan_count=Count('vlans')
).order_by(*VLANGroup._meta.ordering)
vlan_count=get_subquery(VLAN, 'group')
)
serializer_class = serializers.VLANGroupSerializer
filterset_class = filters.VLANGroupFilterSet
@ -276,7 +275,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

View File

@ -1,6 +1,5 @@
import netaddr
from django.conf import settings
from django.db.models import Count, Prefetch
from django.db.models import Prefetch
from django.db.models.expressions import RawSQL
from django.shortcuts import get_object_or_404, redirect, render
from django_tables2 import RequestConfig
@ -79,7 +78,9 @@ class VRFBulkDeleteView(BulkDeleteView):
#
class RIRListView(ObjectListView):
queryset = RIR.objects.annotate(aggregate_count=Count('aggregates')).order_by(*RIR._meta.ordering)
queryset = RIR.objects.annotate(
aggregate_count=get_subquery(Aggregate, 'rir')
)
filterset = filters.RIRFilterSet
filterset_form = forms.RIRFilterForm
table = tables.RIRDetailTable
@ -172,7 +173,9 @@ class RIRBulkImportView(BulkImportView):
class RIRBulkDeleteView(BulkDeleteView):
queryset = RIR.objects.annotate(aggregate_count=Count('aggregates')).order_by(*RIR._meta.ordering)
queryset = RIR.objects.annotate(
aggregate_count=get_subquery(Aggregate, 'rir')
)
filterset = filters.RIRFilterSet
table = tables.RIRTable
@ -184,7 +187,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
@ -652,8 +655,8 @@ class IPAddressBulkDeleteView(BulkDeleteView):
class VLANGroupListView(ObjectListView):
queryset = VLANGroup.objects.prefetch_related('site').annotate(
vlan_count=Count('vlans')
).order_by(*VLANGroup._meta.ordering)
vlan_count=get_subquery(VLAN, 'group')
)
filterset = filters.VLANGroupFilterSet
filterset_form = forms.VLANGroupFilterForm
table = tables.VLANGroupTable
@ -676,8 +679,8 @@ class VLANGroupBulkImportView(BulkImportView):
class VLANGroupBulkDeleteView(BulkDeleteView):
queryset = VLANGroup.objects.prefetch_related('site').annotate(
vlan_count=Count('vlans')
).order_by(*VLANGroup._meta.ordering)
vlan_count=get_subquery(VLAN, 'group')
)
filterset = filters.VLANGroupFilterSet
table = tables.VLANGroupTable

View File

@ -48,8 +48,8 @@ SEARCH_TYPES = OrderedDict((
# Circuits
('provider', {
'queryset': Provider.objects.annotate(
count_circuits=Count('circuits')
).order_by(*Provider._meta.ordering),
count_circuits=get_subquery(Circuit, 'provider')
),
'filterset': ProviderFilterSet,
'table': ProviderTable,
'url': 'circuits:provider_list',
@ -76,17 +76,21 @@ SEARCH_TYPES = OrderedDict((
'url': 'dcim:rack_list',
}),
('rackgroup', {
'queryset': RackGroup.objects.prefetch_related('site').annotate(
rack_count=Count('racks')
).order_by(*RackGroup._meta.ordering),
'queryset': RackGroup.objects.add_related_count(
RackGroup.objects.all(),
Rack,
'group',
'rack_count',
cumulative=True
).prefetch_related('site'),
'filterset': RackGroupFilterSet,
'table': RackGroupTable,
'url': 'dcim:rackgroup_list',
}),
('devicetype', {
'queryset': DeviceType.objects.prefetch_related('manufacturer').annotate(
instance_count=Count('instances')
).order_by(*DeviceType._meta.ordering),
instance_count=get_subquery(Device, 'device_type')
),
'filterset': DeviceTypeFilterSet,
'table': DeviceTypeTable,
'url': 'dcim:devicetype_list',
@ -101,8 +105,8 @@ SEARCH_TYPES = OrderedDict((
}),
('virtualchassis', {
'queryset': VirtualChassis.objects.prefetch_related('master').annotate(
member_count=Count('members', distinct=True)
).order_by(*VirtualChassis._meta.ordering),
member_count=get_subquery(Device, 'virtual_chassis')
),
'filterset': VirtualChassisFilterSet,
'table': VirtualChassisTable,
'url': 'dcim:virtualchassis_list',

View File

@ -1,7 +1,6 @@
import base64
from Crypto.PublicKey import RSA
from django.db.models import Count
from django.http import HttpResponseBadRequest
from rest_framework.exceptions import ValidationError
from rest_framework.permissions import IsAuthenticated
@ -13,6 +12,7 @@ from secrets import filters
from secrets.exceptions import InvalidKey
from secrets.models import Secret, SecretRole, SessionKey, UserKey
from utilities.api import ModelViewSet
from utilities.utils import get_subquery
from . import serializers
ERR_USERKEY_MISSING = "No UserKey found for the current user."
@ -35,8 +35,8 @@ class SecretsRootView(APIRootView):
class SecretRoleViewSet(ModelViewSet):
queryset = SecretRole.objects.annotate(
secret_count=Count('secrets')
).order_by(*SecretRole._meta.ordering)
secret_count=get_subquery(Secret, 'role')
)
serializer_class = serializers.SecretRoleSerializer
filterset_class = filters.SecretRoleFilterSet

View File

@ -2,11 +2,11 @@ import base64
import logging
from django.contrib import messages
from django.db.models import Count
from django.shortcuts import get_object_or_404, redirect, render
from django.utils.html import escape
from django.utils.safestring import mark_safe
from utilities.utils import get_subquery
from utilities.views import (
BulkDeleteView, BulkEditView, BulkImportView, ObjectView, ObjectDeleteView, ObjectEditView, ObjectListView,
)
@ -29,7 +29,9 @@ def get_session_key(request):
#
class SecretRoleListView(ObjectListView):
queryset = SecretRole.objects.annotate(secret_count=Count('secrets')).order_by(*SecretRole._meta.ordering)
queryset = SecretRole.objects.annotate(
secret_count=get_subquery(Secret, 'role')
)
table = tables.SecretRoleTable
@ -49,7 +51,9 @@ class SecretRoleBulkImportView(BulkImportView):
class SecretRoleBulkDeleteView(BulkDeleteView):
queryset = SecretRole.objects.annotate(secret_count=Count('secrets')).order_by(*SecretRole._meta.ordering)
queryset = SecretRole.objects.annotate(
secret_count=get_subquery(Secret, 'role')
)
table = tables.SecretRoleTable

View File

@ -1,4 +1,3 @@
from django.db.models import Count
from django.shortcuts import get_object_or_404
from rest_framework.decorators import action
from rest_framework.response import Response
@ -29,16 +28,16 @@ class VirtualizationRootView(APIRootView):
class ClusterTypeViewSet(ModelViewSet):
queryset = ClusterType.objects.annotate(
cluster_count=Count('clusters')
).order_by(*ClusterType._meta.ordering)
cluster_count=get_subquery(Cluster, 'type')
)
serializer_class = serializers.ClusterTypeSerializer
filterset_class = filters.ClusterTypeFilterSet
class ClusterGroupViewSet(ModelViewSet):
queryset = ClusterGroup.objects.annotate(
cluster_count=Count('clusters')
).order_by(*ClusterGroup._meta.ordering)
cluster_count=get_subquery(Cluster, 'group')
)
serializer_class = serializers.ClusterGroupSerializer
filterset_class = filters.ClusterGroupFilterSet
@ -49,7 +48,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

View File

@ -1,6 +1,6 @@
from django.contrib import messages
from django.db import transaction
from django.db.models import Count, Prefetch
from django.db.models import Prefetch
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
@ -23,7 +23,9 @@ from .models import Cluster, ClusterGroup, ClusterType, VirtualMachine, VMInterf
#
class ClusterTypeListView(ObjectListView):
queryset = ClusterType.objects.annotate(cluster_count=Count('clusters')).order_by(*ClusterType._meta.ordering)
queryset = ClusterType.objects.annotate(
cluster_count=get_subquery(Cluster, 'type')
)
table = tables.ClusterTypeTable
@ -43,7 +45,9 @@ class ClusterTypeBulkImportView(BulkImportView):
class ClusterTypeBulkDeleteView(BulkDeleteView):
queryset = ClusterType.objects.annotate(cluster_count=Count('clusters')).order_by(*ClusterType._meta.ordering)
queryset = ClusterType.objects.annotate(
cluster_count=get_subquery(Cluster, 'type')
)
table = tables.ClusterTypeTable
@ -52,7 +56,9 @@ class ClusterTypeBulkDeleteView(BulkDeleteView):
#
class ClusterGroupListView(ObjectListView):
queryset = ClusterGroup.objects.annotate(cluster_count=Count('clusters')).order_by(*ClusterGroup._meta.ordering)
queryset = ClusterGroup.objects.annotate(
cluster_count=get_subquery(Cluster, 'group')
)
table = tables.ClusterGroupTable
@ -72,7 +78,9 @@ class ClusterGroupBulkImportView(BulkImportView):
class ClusterGroupBulkDeleteView(BulkDeleteView):
queryset = ClusterGroup.objects.annotate(cluster_count=Count('clusters')).order_by(*ClusterGroup._meta.ordering)
queryset = ClusterGroup.objects.annotate(
cluster_count=get_subquery(Cluster, 'group')
)
table = tables.ClusterGroupTable