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

Call Coalesce() inside get_queryset()

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

+ 2 - 3
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

+ 19 - 20
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

+ 1 - 2
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

+ 7 - 8
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

+ 1 - 2
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

+ 7 - 8
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

+ 2 - 1
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):

+ 4 - 5
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