Refactor RelatedObjectCountField to take a single relationship name

This commit is contained in:
Jeremy Stretch 2024-02-15 14:27:33 -05:00
parent 06226a3c60
commit f6338e23ba
16 changed files with 81 additions and 82 deletions

View File

@ -36,7 +36,7 @@ class NestedProviderNetworkSerializer(WritableNestedSerializer):
)
class NestedProviderSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='circuits-api:provider-detail')
circuit_count = RelatedObjectCountField('circuits.circuit', 'provider')
circuit_count = RelatedObjectCountField('circuits')
class Meta:
model = Provider
@ -64,7 +64,7 @@ class NestedProviderAccountSerializer(WritableNestedSerializer):
)
class NestedCircuitTypeSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='circuits-api:circuittype-detail')
circuit_count = RelatedObjectCountField('circuits.circuit', 'type')
circuit_count = RelatedObjectCountField('circuits')
class Meta:
model = CircuitType

View File

@ -32,7 +32,7 @@ class ProviderSerializer(NetBoxModelSerializer):
)
# Related object counts
circuit_count = RelatedObjectCountField('circuits.circuit', 'provider')
circuit_count = RelatedObjectCountField('circuits')
class Meta:
model = Provider
@ -82,7 +82,7 @@ class CircuitTypeSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='circuits-api:circuittype-detail')
# Related object counts
circuit_count = RelatedObjectCountField('circuits.circuit', 'type')
circuit_count = RelatedObjectCountField('circuits')
class Meta:
model = CircuitType

View File

@ -28,7 +28,7 @@ class DataSourceSerializer(NetBoxModelSerializer):
)
# Related object counts
file_count = RelatedObjectCountField('core.datafile', 'source')
file_count = RelatedObjectCountField('datafiles')
class Meta:
model = DataSource

View File

@ -111,7 +111,7 @@ class NestedLocationSerializer(WritableNestedSerializer):
)
class NestedRackRoleSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rackrole-detail')
rack_count = RelatedObjectCountField('dcim.rack', 'role')
rack_count = RelatedObjectCountField('racks')
class Meta:
model = models.RackRole
@ -123,7 +123,7 @@ class NestedRackRoleSerializer(WritableNestedSerializer):
)
class NestedRackSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rack-detail')
device_count = RelatedObjectCountField('dcim.device', 'rack')
device_count = RelatedObjectCountField('devices')
class Meta:
model = models.Rack
@ -151,7 +151,7 @@ class NestedRackReservationSerializer(WritableNestedSerializer):
)
class NestedManufacturerSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:manufacturer-detail')
devicetype_count = RelatedObjectCountField('dcim.devicetype', 'manufacturer')
devicetype_count = RelatedObjectCountField('device_types')
class Meta:
model = models.Manufacturer
@ -164,7 +164,7 @@ class NestedManufacturerSerializer(WritableNestedSerializer):
class NestedDeviceTypeSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:devicetype-detail')
manufacturer = NestedManufacturerSerializer(read_only=True)
device_count = RelatedObjectCountField('dcim.device', 'device_type')
device_count = RelatedObjectCountField('instances')
class Meta:
model = models.DeviceType
@ -274,8 +274,8 @@ class NestedInventoryItemTemplateSerializer(WritableNestedSerializer):
)
class NestedDeviceRoleSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:devicerole-detail')
device_count = RelatedObjectCountField('dcim.device', 'role')
virtualmachine_count = RelatedObjectCountField('virtualization.virtualmachine', 'role')
device_count = RelatedObjectCountField('devices')
virtualmachine_count = RelatedObjectCountField('virtual_machines')
class Meta:
model = models.DeviceRole
@ -287,8 +287,8 @@ class NestedDeviceRoleSerializer(WritableNestedSerializer):
)
class NestedPlatformSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:platform-detail')
device_count = RelatedObjectCountField('dcim.device', 'platform')
virtualmachine_count = RelatedObjectCountField('virtualization.virtualmachine', 'platform')
device_count = RelatedObjectCountField('devices')
virtualmachine_count = RelatedObjectCountField('virtual_machines')
class Meta:
model = models.Platform
@ -445,7 +445,7 @@ class NestedInventoryItemSerializer(WritableNestedSerializer):
)
class NestedInventoryItemRoleSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:inventoryitemrole-detail')
inventoryitem_count = RelatedObjectCountField('dcim.inventoryitem', 'role')
inventoryitem_count = RelatedObjectCountField('inventory_items')
class Meta:
model = models.InventoryItemRole
@ -490,7 +490,7 @@ class NestedVirtualChassisSerializer(WritableNestedSerializer):
)
class NestedPowerPanelSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:powerpanel-detail')
powerfeed_count = RelatedObjectCountField('dcim.powerfeed', 'power_panel')
powerfeed_count = RelatedObjectCountField('powerfeeds')
class Meta:
model = models.PowerPanel

View File

@ -144,12 +144,12 @@ class SiteSerializer(NetBoxModelSerializer):
)
# Related object counts
circuit_count = RelatedObjectCountField('circuits.circuit', 'terminations__site')
device_count = RelatedObjectCountField('dcim.device', 'site')
prefix_count = RelatedObjectCountField('ipam.prefix', 'site')
rack_count = RelatedObjectCountField('dcim.rack', 'site')
vlan_count = RelatedObjectCountField('ipam.vlan', 'site')
virtualmachine_count = RelatedObjectCountField('virtualization.virtualmachine', 'site')
circuit_count = RelatedObjectCountField('circuit_terminations')
device_count = RelatedObjectCountField('devices')
prefix_count = RelatedObjectCountField('prefixes')
rack_count = RelatedObjectCountField('racks')
vlan_count = RelatedObjectCountField('vlans')
virtualmachine_count = RelatedObjectCountField('virtual_machines')
class Meta:
model = Site
@ -186,7 +186,7 @@ class RackRoleSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:rackrole-detail')
# Related object counts
rack_count = RelatedObjectCountField('dcim.rack', 'role')
rack_count = RelatedObjectCountField('racks')
class Meta:
model = RackRole
@ -211,8 +211,8 @@ class RackSerializer(NetBoxModelSerializer):
weight_unit = ChoiceField(choices=WeightUnitChoices, allow_blank=True, required=False, allow_null=True)
# Related object counts
device_count = RelatedObjectCountField('dcim.device', 'rack')
powerfeed_count = RelatedObjectCountField('dcim.powerfeed', 'rack')
device_count = RelatedObjectCountField('devices')
powerfeed_count = RelatedObjectCountField('powerfeeds')
class Meta:
model = Rack
@ -305,9 +305,9 @@ class ManufacturerSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:manufacturer-detail')
# Related object counts
devicetype_count = RelatedObjectCountField('dcim.devicetype', 'manufacturer')
inventoryitem_count = RelatedObjectCountField('dcim.inventoryitem', 'manufacturer')
platform_count = RelatedObjectCountField('dcim.platform', 'manufacturer')
devicetype_count = RelatedObjectCountField('device_types')
inventoryitem_count = RelatedObjectCountField('inventory_items')
platform_count = RelatedObjectCountField('platforms')
class Meta:
model = Manufacturer
@ -345,7 +345,7 @@ class DeviceTypeSerializer(NetBoxModelSerializer):
inventory_item_template_count = serializers.IntegerField(read_only=True)
# Related object counts
device_count = RelatedObjectCountField('dcim.device', 'device_type')
device_count = RelatedObjectCountField('instances')
class Meta:
model = DeviceType
@ -646,8 +646,8 @@ class DeviceRoleSerializer(NetBoxModelSerializer):
config_template = NestedConfigTemplateSerializer(required=False, allow_null=True, default=None)
# Related object counts
device_count = RelatedObjectCountField('dcim.device', 'role')
virtualmachine_count = RelatedObjectCountField('virtualization.virtualmachine', 'role')
device_count = RelatedObjectCountField('devices')
virtualmachine_count = RelatedObjectCountField('virtual_machines')
class Meta:
model = DeviceRole
@ -663,8 +663,8 @@ class PlatformSerializer(NetBoxModelSerializer):
config_template = NestedConfigTemplateSerializer(required=False, allow_null=True, default=None)
# Related object counts
device_count = RelatedObjectCountField('dcim.device', 'platform')
virtualmachine_count = RelatedObjectCountField('virtualization.virtualmachine', 'platform')
device_count = RelatedObjectCountField('devices')
virtualmachine_count = RelatedObjectCountField('virtual_machines')
class Meta:
model = Platform
@ -773,7 +773,7 @@ class VirtualDeviceContextSerializer(NetBoxModelSerializer):
status = ChoiceField(choices=VirtualDeviceContextStatusChoices)
# Related object counts
interface_count = RelatedObjectCountField('dcim.interface', 'vdcs')
interface_count = RelatedObjectCountField('interfaces')
class Meta:
model = VirtualDeviceContext
@ -1106,7 +1106,7 @@ class InventoryItemRoleSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='dcim-api:inventoryitemrole-detail')
# Related object counts
inventoryitem_count = RelatedObjectCountField('dcim.inventoryitem', 'role')
inventoryitem_count = RelatedObjectCountField('inventory_items')
class Meta:
model = InventoryItemRole
@ -1220,7 +1220,7 @@ class PowerPanelSerializer(NetBoxModelSerializer):
)
# Related object counts
powerfeed_count = RelatedObjectCountField('dcim.powerfeed', 'power_panel')
powerfeed_count = RelatedObjectCountField('powerfeeds')
class Meta:
model = PowerPanel

View File

@ -7,6 +7,7 @@ from rest_framework.response import Response
from rest_framework.routers import APIRootView
from rest_framework.viewsets import ViewSet
from circuits.models import Circuit
from dcim import filtersets
from dcim.constants import CABLE_TRACE_SVG_DEFAULT_WIDTH
from dcim.models import *
@ -20,6 +21,7 @@ from netbox.api.viewsets.mixins import SequentialBulkCreatesMixin
from netbox.constants import NESTED_SERIALIZER_PREFIX
from utilities.api import get_serializer_for_model
from utilities.query_functions import CollateAsChar
from utilities.utils import count_related
from . import serializers
from .exceptions import MissingFilterException

View File

@ -289,7 +289,7 @@ class TagSerializer(ValidatedModelSerializer):
)
# Related object counts
tagged_items = RelatedObjectCountField('extras.taggeditem', 'tag')
tagged_items = RelatedObjectCountField('extras_taggeditem_items')
class Meta:
model = Tag

View File

@ -59,7 +59,7 @@ class NestedASNSerializer(WritableNestedSerializer):
)
class NestedVRFSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vrf-detail')
prefix_count = RelatedObjectCountField('ipam.prefix', 'vrf')
prefix_count = RelatedObjectCountField('prefixes')
class Meta:
model = models.VRF
@ -87,7 +87,7 @@ class NestedRouteTargetSerializer(WritableNestedSerializer):
)
class NestedRIRSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:rir-detail')
aggregate_count = RelatedObjectCountField('ipam.aggregate', 'rir')
aggregate_count = RelatedObjectCountField('aggregates')
class Meta:
model = models.RIR
@ -133,8 +133,8 @@ class NestedFHRPGroupAssignmentSerializer(WritableNestedSerializer):
)
class NestedRoleSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:role-detail')
prefix_count = RelatedObjectCountField('ipam.prefix', 'role')
vlan_count = RelatedObjectCountField('ipam.vlan', 'role')
prefix_count = RelatedObjectCountField('prefixes')
vlan_count = RelatedObjectCountField('vlans')
class Meta:
model = models.Role
@ -146,7 +146,7 @@ class NestedRoleSerializer(WritableNestedSerializer):
)
class NestedVLANGroupSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:vlangroup-detail')
vlan_count = RelatedObjectCountField('ipam.vlan', 'group')
vlan_count = RelatedObjectCountField('vlans')
class Meta:
model = models.VLANGroup

View File

@ -45,8 +45,8 @@ class ASNSerializer(NetBoxModelSerializer):
tenant = NestedTenantSerializer(required=False, allow_null=True)
# Related object counts
site_count = RelatedObjectCountField('dcim.site', 'asns')
provider_count = RelatedObjectCountField('circuits.provider', 'asns')
site_count = RelatedObjectCountField('sites')
provider_count = RelatedObjectCountField('providers')
class Meta:
model = ASN
@ -94,8 +94,8 @@ class VRFSerializer(NetBoxModelSerializer):
)
# Related object counts
ipaddress_count = RelatedObjectCountField('ipam.ipaddress', 'vrf')
prefix_count = RelatedObjectCountField('ipam.prefix', 'vrf')
ipaddress_count = RelatedObjectCountField('ip_addresses')
prefix_count = RelatedObjectCountField('prefixes')
class Meta:
model = VRF
@ -130,7 +130,7 @@ class RIRSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:rir-detail')
# Related object counts
aggregate_count = RelatedObjectCountField('ipam.aggregate', 'rir')
aggregate_count = RelatedObjectCountField('aggregates')
class Meta:
model = RIR
@ -203,8 +203,8 @@ class RoleSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='ipam-api:role-detail')
# Related object counts
prefix_count = RelatedObjectCountField('ipam.prefix', 'role')
vlan_count = RelatedObjectCountField('ipam.vlan', 'role')
prefix_count = RelatedObjectCountField('prefixes')
vlan_count = RelatedObjectCountField('vlans')
class Meta:
model = Role
@ -229,7 +229,7 @@ class VLANGroupSerializer(NetBoxModelSerializer):
utilization = serializers.CharField(read_only=True)
# Related object counts
vlan_count = RelatedObjectCountField('ipam.vlan', 'group')
vlan_count = RelatedObjectCountField('vlans')
class Meta:
model = VLANGroup
@ -259,7 +259,7 @@ class VLANSerializer(NetBoxModelSerializer):
l2vpn_termination = NestedL2VPNTerminationSerializer(read_only=True, allow_null=True)
# Related object counts
prefix_count = RelatedObjectCountField('ipam.prefix', 'vlan')
prefix_count = RelatedObjectCountField('prefixes')
class Meta:
model = VLAN

View File

@ -1,7 +1,6 @@
from django.apps import apps
from django.core.exceptions import ObjectDoesNotExist
from drf_spectacular.utils import extend_schema_field
from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema_field
from netaddr import IPNetwork
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
@ -146,13 +145,7 @@ class RelatedObjectCountField(serializers.ReadOnlyField):
is detected by get_annotations_for_serializer() when determining the annotations to be added to a queryset
depending on the serializer fields selected for inclusion in the response.
"""
def __init__(self, model, related_field, **kwargs):
super().__init__(**kwargs)
def __init__(self, relation, **kwargs):
self.relation = relation
# Set the model and field names passed on the field
if type(model) is str:
app_label, model_name = model.split('.')
self.model = apps.get_model(app_label, model_name)
else:
self.model = model
self.related_field = related_field
super().__init__(**kwargs)

View File

@ -34,16 +34,16 @@ class TenantSerializer(NetBoxModelSerializer):
group = NestedTenantGroupSerializer(required=False, allow_null=True)
# Related object counts
circuit_count = RelatedObjectCountField('circuits.circuit', 'tenant')
device_count = RelatedObjectCountField('dcim.device', 'tenant')
rack_count = RelatedObjectCountField('dcim.rack', 'tenant')
site_count = RelatedObjectCountField('dcim.site', 'tenant')
ipaddress_count = RelatedObjectCountField('ipam.ipaddress', 'tenant')
prefix_count = RelatedObjectCountField('ipam.prefix', 'tenant')
vlan_count = RelatedObjectCountField('ipam.vlan', 'tenant')
vrf_count = RelatedObjectCountField('ipam.vrf', 'tenant')
virtualmachine_count = RelatedObjectCountField('virtualization.virtualmachine', 'tenant')
cluster_count = RelatedObjectCountField('virtualization.cluster', 'tenant')
circuit_count = RelatedObjectCountField('circuits')
device_count = RelatedObjectCountField('devices')
rack_count = RelatedObjectCountField('racks')
site_count = RelatedObjectCountField('sites')
ipaddress_count = RelatedObjectCountField('ip_addresses')
prefix_count = RelatedObjectCountField('prefixes')
vlan_count = RelatedObjectCountField('vlans')
vrf_count = RelatedObjectCountField('vrfs')
virtualmachine_count = RelatedObjectCountField('virtual_machines')
cluster_count = RelatedObjectCountField('clusters')
class Meta:
model = Tenant

View File

@ -17,6 +17,7 @@ from utilities.utils import count_related
from .utils import dynamic_import
__all__ = (
'get_annotations_for_serializer',
'get_graphql_type_for_model',
'get_prefetches_for_serializer',
'get_serializer_for_model',
@ -143,9 +144,12 @@ def get_annotations_for_serializer(serializer_class, fields_to_include=None):
if not fields_to_include:
fields_to_include = serializer_class.Meta.fields
model = serializer_class.Meta.model
for field_name, field in serializer_class._declared_fields.items():
if field_name in fields_to_include and type(field) is RelatedObjectCountField:
annotations[field_name] = count_related(field.model, field.related_field)
related_field = model._meta.get_field(field.relation).field
annotations[field_name] = count_related(related_field.model, related_field.name)
return annotations

View File

@ -24,7 +24,7 @@ __all__ = [
)
class NestedClusterTypeSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:clustertype-detail')
cluster_count = RelatedObjectCountField('virtualization.cluster', 'type')
cluster_count = RelatedObjectCountField('clusters')
class Meta:
model = ClusterType
@ -36,7 +36,7 @@ class NestedClusterTypeSerializer(WritableNestedSerializer):
)
class NestedClusterGroupSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:clustergroup-detail')
cluster_count = RelatedObjectCountField('virtualization.cluster', 'group')
cluster_count = RelatedObjectCountField('clusters')
class Meta:
model = ClusterGroup
@ -48,7 +48,7 @@ class NestedClusterGroupSerializer(WritableNestedSerializer):
)
class NestedClusterSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:cluster-detail')
virtualmachine_count = RelatedObjectCountField('virtualization.virtualmachine', 'cluster')
virtualmachine_count = RelatedObjectCountField('virtual_machines')
class Meta:
model = Cluster

View File

@ -25,7 +25,7 @@ class ClusterTypeSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:clustertype-detail')
# Related object counts
cluster_count = RelatedObjectCountField('virtualization.cluster', 'type')
cluster_count = RelatedObjectCountField('clusters')
class Meta:
model = ClusterType
@ -39,7 +39,7 @@ class ClusterGroupSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='virtualization-api:clustergroup-detail')
# Related object counts
cluster_count = RelatedObjectCountField('virtualization.cluster', 'group')
cluster_count = RelatedObjectCountField('clusters')
class Meta:
model = ClusterGroup
@ -58,8 +58,8 @@ class ClusterSerializer(NetBoxModelSerializer):
site = NestedSiteSerializer(required=False, allow_null=True, default=None)
# Related object counts
device_count = RelatedObjectCountField('dcim.device', 'cluster')
virtualmachine_count = RelatedObjectCountField('virtualization.virtualmachine', 'cluster')
device_count = RelatedObjectCountField('devices')
virtualmachine_count = RelatedObjectCountField('virtual_machines')
class Meta:
model = Cluster

View File

@ -24,7 +24,7 @@ __all__ = (
)
class NestedTunnelGroupSerializer(WritableNestedSerializer):
url = serializers.HyperlinkedIdentityField(view_name='vpn-api:tunnelgroup-detail')
tunnel_count = RelatedObjectCountField('vpn.tunnel', 'group')
tunnel_count = RelatedObjectCountField('tunnels')
class Meta:
model = models.TunnelGroup

View File

@ -31,7 +31,7 @@ class TunnelGroupSerializer(NetBoxModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='vpn-api:tunnelgroup-detail')
# Related object counts
tunnel_count = RelatedObjectCountField('vpn.tunnel', 'group')
tunnel_count = RelatedObjectCountField('tunnels')
class Meta:
model = TunnelGroup
@ -62,7 +62,7 @@ class TunnelSerializer(NetBoxModelSerializer):
)
# Related object counts
terminations_count = RelatedObjectCountField('vpn.tunneltermination', 'tunnel')
terminations_count = RelatedObjectCountField('terminations')
class Meta:
model = Tunnel