From 91083fd6c52f11a4af163be1978b9a75d66ea639 Mon Sep 17 00:00:00 2001 From: Jeremy Stretch Date: Thu, 17 Dec 2020 14:45:50 -0500 Subject: [PATCH] Call Coalesce() inside get_queryset() --- netbox/circuits/api/views.py | 5 ++-- netbox/dcim/api/views.py | 39 +++++++++++++++--------------- netbox/extras/api/views.py | 3 +-- netbox/ipam/api/views.py | 15 ++++++------ netbox/secrets/api/views.py | 3 +-- netbox/tenancy/api/views.py | 15 ++++++------ netbox/utilities/utils.py | 3 ++- netbox/virtualization/api/views.py | 9 +++---- 8 files changed, 43 insertions(+), 49 deletions(-) diff --git a/netbox/circuits/api/views.py b/netbox/circuits/api/views.py index ef5a944e2..ad497ee5f 100644 --- a/netbox/circuits/api/views.py +++ b/netbox/circuits/api/views.py @@ -1,5 +1,4 @@ from django.db.models import Prefetch -from django.db.models.functions import Coalesce from rest_framework.routers import APIRootView from circuits import filters @@ -25,7 +24,7 @@ class CircuitsRootView(APIRootView): class ProviderViewSet(CustomFieldModelViewSet): queryset = Provider.objects.prefetch_related('tags').annotate( - circuit_count=Coalesce(get_subquery(Circuit, 'provider'), 0) + circuit_count=get_subquery(Circuit, 'provider') ) serializer_class = serializers.ProviderSerializer filterset_class = filters.ProviderFilterSet @@ -37,7 +36,7 @@ class ProviderViewSet(CustomFieldModelViewSet): class CircuitTypeViewSet(ModelViewSet): queryset = CircuitType.objects.annotate( - circuit_count=Coalesce(get_subquery(Circuit, 'type'), 0) + circuit_count=get_subquery(Circuit, 'type') ) serializer_class = serializers.CircuitTypeSerializer filterset_class = filters.CircuitTypeFilterSet diff --git a/netbox/dcim/api/views.py b/netbox/dcim/api/views.py index f5149b876..efb8e994d 100644 --- a/netbox/dcim/api/views.py +++ b/netbox/dcim/api/views.py @@ -3,7 +3,6 @@ from collections import OrderedDict from django.conf import settings from django.db.models import F -from django.db.models.functions import Coalesce from django.http import HttpResponseForbidden, HttpResponse from django.shortcuts import get_object_or_404 from drf_yasg import openapi @@ -120,12 +119,12 @@ class SiteViewSet(CustomFieldModelViewSet): queryset = Site.objects.prefetch_related( 'region', 'tenant', 'tags' ).annotate( - device_count=Coalesce(get_subquery(Device, 'site'), 0), - rack_count=Coalesce(get_subquery(Rack, 'site'), 0), - prefix_count=Coalesce(get_subquery(Prefix, 'site'), 0), - vlan_count=Coalesce(get_subquery(VLAN, 'site'), 0), - circuit_count=Coalesce(get_subquery(Circuit, 'terminations__site'), 0), - virtualmachine_count=Coalesce(get_subquery(VirtualMachine, 'cluster__site'), 0), + 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') ) serializer_class = serializers.SiteSerializer filterset_class = filters.SiteFilterSet @@ -153,7 +152,7 @@ class RackGroupViewSet(ModelViewSet): class RackRoleViewSet(ModelViewSet): queryset = RackRole.objects.annotate( - rack_count=Coalesce(get_subquery(Rack, 'role'), 0) + rack_count=get_subquery(Rack, 'role') ) serializer_class = serializers.RackRoleSerializer filterset_class = filters.RackRoleFilterSet @@ -167,8 +166,8 @@ class RackViewSet(CustomFieldModelViewSet): queryset = Rack.objects.prefetch_related( 'site', 'group__site', 'role', 'tenant', 'tags' ).annotate( - device_count=Coalesce(get_subquery(Device, 'rack'), 0), - powerfeed_count=Coalesce(get_subquery(PowerFeed, 'rack'), 0) + device_count=get_subquery(Device, 'rack'), + powerfeed_count=get_subquery(PowerFeed, 'rack') ) serializer_class = serializers.RackSerializer filterset_class = filters.RackFilterSet @@ -241,9 +240,9 @@ class RackReservationViewSet(ModelViewSet): class ManufacturerViewSet(ModelViewSet): queryset = Manufacturer.objects.annotate( - devicetype_count=Coalesce(get_subquery(DeviceType, 'manufacturer'), 0), - inventoryitem_count=Coalesce(get_subquery(InventoryItem, 'manufacturer'), 0), - platform_count=Coalesce(get_subquery(Platform, 'manufacturer'), 0) + devicetype_count=get_subquery(DeviceType, 'manufacturer'), + inventoryitem_count=get_subquery(InventoryItem, 'manufacturer'), + platform_count=get_subquery(Platform, 'manufacturer') ) serializer_class = serializers.ManufacturerSerializer filterset_class = filters.ManufacturerFilterSet @@ -255,7 +254,7 @@ class ManufacturerViewSet(ModelViewSet): class DeviceTypeViewSet(CustomFieldModelViewSet): queryset = DeviceType.objects.prefetch_related('manufacturer', 'tags').annotate( - device_count=Coalesce(get_subquery(Device, 'device_type'), 0) + device_count=get_subquery(Device, 'device_type') ) serializer_class = serializers.DeviceTypeSerializer filterset_class = filters.DeviceTypeFilterSet @@ -319,8 +318,8 @@ class DeviceBayTemplateViewSet(ModelViewSet): class DeviceRoleViewSet(ModelViewSet): queryset = DeviceRole.objects.annotate( - device_count=Coalesce(get_subquery(Device, 'device_role'), 0), - virtualmachine_count=Coalesce(get_subquery(VirtualMachine, 'role'), 0) + device_count=get_subquery(Device, 'device_role'), + virtualmachine_count=get_subquery(VirtualMachine, 'role') ) serializer_class = serializers.DeviceRoleSerializer filterset_class = filters.DeviceRoleFilterSet @@ -332,8 +331,8 @@ class DeviceRoleViewSet(ModelViewSet): class PlatformViewSet(ModelViewSet): queryset = Platform.objects.annotate( - device_count=Coalesce(get_subquery(Device, 'platform'), 0), - virtualmachine_count=Coalesce(get_subquery(VirtualMachine, 'platform'), 0) + device_count=get_subquery(Device, 'platform'), + virtualmachine_count=get_subquery(VirtualMachine, 'platform') ) serializer_class = serializers.PlatformSerializer filterset_class = filters.PlatformFilterSet @@ -597,7 +596,7 @@ class CableViewSet(ModelViewSet): class VirtualChassisViewSet(ModelViewSet): queryset = VirtualChassis.objects.prefetch_related('tags').annotate( - member_count=Coalesce(get_subquery(Device, 'virtual_chassis'), 0) + member_count=get_subquery(Device, 'virtual_chassis') ) serializer_class = serializers.VirtualChassisSerializer filterset_class = filters.VirtualChassisFilterSet @@ -611,7 +610,7 @@ class PowerPanelViewSet(ModelViewSet): queryset = PowerPanel.objects.prefetch_related( 'site', 'rack_group' ).annotate( - powerfeed_count=Coalesce(get_subquery(PowerFeed, 'power_panel'), 0) + powerfeed_count=get_subquery(PowerFeed, 'power_panel') ) serializer_class = serializers.PowerPanelSerializer filterset_class = filters.PowerPanelFilterSet diff --git a/netbox/extras/api/views.py b/netbox/extras/api/views.py index fcd9add7c..38077c89a 100644 --- a/netbox/extras/api/views.py +++ b/netbox/extras/api/views.py @@ -1,5 +1,4 @@ from django.contrib.contenttypes.models import ContentType -from django.db.models.functions import Coalesce from django.http import Http404 from django_rq.queues import get_connection from rest_framework import status @@ -103,7 +102,7 @@ class ExportTemplateViewSet(ModelViewSet): class TagViewSet(ModelViewSet): queryset = Tag.objects.annotate( - tagged_items=Coalesce(get_subquery(TaggedItem, 'tag'), 0) + tagged_items=get_subquery(TaggedItem, 'tag') ) serializer_class = serializers.TagSerializer filterset_class = filters.TagFilterSet diff --git a/netbox/ipam/api/views.py b/netbox/ipam/api/views.py index fb38edf46..9d09bbe03 100644 --- a/netbox/ipam/api/views.py +++ b/netbox/ipam/api/views.py @@ -1,5 +1,4 @@ from django.conf import settings -from django.db.models.functions import Coalesce from django.shortcuts import get_object_or_404 from django_pglocks import advisory_lock from drf_yasg.utils import swagger_auto_schema @@ -33,8 +32,8 @@ class VRFViewSet(CustomFieldModelViewSet): queryset = VRF.objects.prefetch_related('tenant').prefetch_related( 'import_targets', 'export_targets', 'tags' ).annotate( - ipaddress_count=Coalesce(get_subquery(IPAddress, 'vrf'), 0), - prefix_count=Coalesce(get_subquery(Prefix, 'vrf'), 0) + ipaddress_count=get_subquery(IPAddress, 'vrf'), + prefix_count=get_subquery(Prefix, 'vrf') ) serializer_class = serializers.VRFSerializer filterset_class = filters.VRFFilterSet @@ -56,7 +55,7 @@ class RouteTargetViewSet(CustomFieldModelViewSet): class RIRViewSet(ModelViewSet): queryset = RIR.objects.annotate( - aggregate_count=Coalesce(get_subquery(Aggregate, 'rir'), 0) + aggregate_count=get_subquery(Aggregate, 'rir') ) serializer_class = serializers.RIRSerializer filterset_class = filters.RIRFilterSet @@ -78,8 +77,8 @@ class AggregateViewSet(CustomFieldModelViewSet): class RoleViewSet(ModelViewSet): queryset = Role.objects.annotate( - prefix_count=Coalesce(get_subquery(Prefix, 'role'), 0), - vlan_count=Coalesce(get_subquery(VLAN, 'role'), 0) + prefix_count=get_subquery(Prefix, 'role'), + vlan_count=get_subquery(VLAN, 'role') ) serializer_class = serializers.RoleSerializer filterset_class = filters.RoleFilterSet @@ -273,7 +272,7 @@ class IPAddressViewSet(CustomFieldModelViewSet): class VLANGroupViewSet(ModelViewSet): queryset = VLANGroup.objects.prefetch_related('site').annotate( - vlan_count=Coalesce(get_subquery(VLAN, 'group'), 0) + vlan_count=get_subquery(VLAN, 'group') ) serializer_class = serializers.VLANGroupSerializer filterset_class = filters.VLANGroupFilterSet @@ -287,7 +286,7 @@ class VLANViewSet(CustomFieldModelViewSet): queryset = VLAN.objects.prefetch_related( 'site', 'group', 'tenant', 'role', 'tags' ).annotate( - prefix_count=Coalesce(get_subquery(Prefix, 'vlan'), 0) + prefix_count=get_subquery(Prefix, 'vlan') ) serializer_class = serializers.VLANSerializer filterset_class = filters.VLANFilterSet diff --git a/netbox/secrets/api/views.py b/netbox/secrets/api/views.py index 617da5c6e..1153b0508 100644 --- a/netbox/secrets/api/views.py +++ b/netbox/secrets/api/views.py @@ -1,7 +1,6 @@ import base64 from Crypto.PublicKey import RSA -from django.db.models.functions import Coalesce from django.http import HttpResponseBadRequest from rest_framework.exceptions import ValidationError from rest_framework.permissions import IsAuthenticated @@ -36,7 +35,7 @@ class SecretsRootView(APIRootView): class SecretRoleViewSet(ModelViewSet): queryset = SecretRole.objects.annotate( - secret_count=Coalesce(get_subquery(Secret, 'role'), 0) + secret_count=get_subquery(Secret, 'role') ) serializer_class = serializers.SecretRoleSerializer filterset_class = filters.SecretRoleFilterSet diff --git a/netbox/tenancy/api/views.py b/netbox/tenancy/api/views.py index 142203b58..34be4991e 100644 --- a/netbox/tenancy/api/views.py +++ b/netbox/tenancy/api/views.py @@ -1,4 +1,3 @@ -from django.db.models.functions import Coalesce from rest_framework.routers import APIRootView from circuits.models import Circuit @@ -47,13 +46,13 @@ class TenantViewSet(CustomFieldModelViewSet): ).annotate( circuit_count=get_subquery(Circuit, 'tenant'), device_count=get_subquery(Device, 'tenant'), - ipaddress_count=Coalesce(get_subquery(IPAddress, 'tenant'), 0), - prefix_count=Coalesce(get_subquery(Prefix, 'tenant'), 0), - rack_count=Coalesce(get_subquery(Rack, 'tenant'), 0), - site_count=Coalesce(get_subquery(Site, 'tenant'), 0), - virtualmachine_count=Coalesce(get_subquery(VirtualMachine, 'tenant'), 0), - vlan_count=Coalesce(get_subquery(VLAN, 'tenant'), 0), - vrf_count=Coalesce(get_subquery(VRF, 'tenant'), 0) + ipaddress_count=get_subquery(IPAddress, 'tenant'), + prefix_count=get_subquery(Prefix, 'tenant'), + rack_count=get_subquery(Rack, 'tenant'), + site_count=get_subquery(Site, 'tenant'), + virtualmachine_count=get_subquery(VirtualMachine, 'tenant'), + vlan_count=get_subquery(VLAN, 'tenant'), + vrf_count=get_subquery(VRF, 'tenant') ) serializer_class = serializers.TenantSerializer filterset_class = filters.TenantFilterSet diff --git a/netbox/utilities/utils.py b/netbox/utilities/utils.py index 52a951555..19e08dfd4 100644 --- a/netbox/utilities/utils.py +++ b/netbox/utilities/utils.py @@ -5,6 +5,7 @@ from itertools import count, groupby from django.core.serializers import serialize from django.db.models import Count, OuterRef, Subquery +from django.db.models.functions import Coalesce from jinja2 import Environment from dcim.choices import CableLengthUnitChoices @@ -79,7 +80,7 @@ def get_subquery(model, field): ).values('c') ) - return subquery + return Coalesce(subquery, 0) def serialize_object(obj, extra=None, exclude=None): diff --git a/netbox/virtualization/api/views.py b/netbox/virtualization/api/views.py index 82952ad9a..a3dea00df 100644 --- a/netbox/virtualization/api/views.py +++ b/netbox/virtualization/api/views.py @@ -1,4 +1,3 @@ -from django.db.models.functions import Coalesce from rest_framework.routers import APIRootView from dcim.models import Device @@ -23,7 +22,7 @@ class VirtualizationRootView(APIRootView): class ClusterTypeViewSet(ModelViewSet): queryset = ClusterType.objects.annotate( - cluster_count=Coalesce(get_subquery(Cluster, 'type'), 0) + cluster_count=get_subquery(Cluster, 'type') ) serializer_class = serializers.ClusterTypeSerializer filterset_class = filters.ClusterTypeFilterSet @@ -31,7 +30,7 @@ class ClusterTypeViewSet(ModelViewSet): class ClusterGroupViewSet(ModelViewSet): queryset = ClusterGroup.objects.annotate( - cluster_count=Coalesce(get_subquery(Cluster, 'group'), 0) + cluster_count=get_subquery(Cluster, 'group') ) serializer_class = serializers.ClusterGroupSerializer filterset_class = filters.ClusterGroupFilterSet @@ -41,8 +40,8 @@ class ClusterViewSet(CustomFieldModelViewSet): queryset = Cluster.objects.prefetch_related( 'type', 'group', 'tenant', 'site', 'tags' ).annotate( - device_count=Coalesce(get_subquery(Device, 'cluster'), 0), - virtualmachine_count=Coalesce(get_subquery(VirtualMachine, 'cluster'), 0) + device_count=get_subquery(Device, 'cluster'), + virtualmachine_count=get_subquery(VirtualMachine, 'cluster') ) serializer_class = serializers.ClusterSerializer filterset_class = filters.ClusterFilterSet