Fixes #19970: Report device & VM counts for child device roles on parents

This commit is contained in:
Jeremy Stretch 2025-08-20 16:13:33 -04:00
parent 53c890c081
commit 92fba0bed4
3 changed files with 30 additions and 8 deletions

View File

@ -1,3 +1,5 @@
from rest_framework import serializers
from dcim.models import DeviceRole, InventoryItemRole from dcim.models import DeviceRole, InventoryItemRole
from extras.api.serializers_.configtemplates import ConfigTemplateSerializer from extras.api.serializers_.configtemplates import ConfigTemplateSerializer
from netbox.api.fields import RelatedObjectCountField from netbox.api.fields import RelatedObjectCountField
@ -13,10 +15,8 @@ __all__ = (
class DeviceRoleSerializer(NestedGroupModelSerializer): class DeviceRoleSerializer(NestedGroupModelSerializer):
parent = NestedDeviceRoleSerializer(required=False, allow_null=True, default=None) parent = NestedDeviceRoleSerializer(required=False, allow_null=True, default=None)
config_template = ConfigTemplateSerializer(nested=True, required=False, allow_null=True, default=None) config_template = ConfigTemplateSerializer(nested=True, required=False, allow_null=True, default=None)
device_count = serializers.IntegerField(read_only=True, default=0)
# Related object counts virtualmachine_count = serializers.IntegerField(read_only=True, default=0)
device_count = RelatedObjectCountField('devices')
virtualmachine_count = RelatedObjectCountField('virtual_machines')
class Meta: class Meta:
model = DeviceRole model = DeviceRole

View File

@ -20,6 +20,7 @@ from netbox.api.viewsets import NetBoxModelViewSet, MPTTLockedMixin
from netbox.api.viewsets.mixins import SequentialBulkCreatesMixin from netbox.api.viewsets.mixins import SequentialBulkCreatesMixin
from utilities.api import get_serializer_for_model from utilities.api import get_serializer_for_model
from utilities.query_functions import CollateAsChar from utilities.query_functions import CollateAsChar
from virtualization.models import VirtualMachine
from . import serializers from . import serializers
from .exceptions import MissingFilterException from .exceptions import MissingFilterException
@ -351,7 +352,19 @@ class InventoryItemTemplateViewSet(MPTTLockedMixin, NetBoxModelViewSet):
# #
class DeviceRoleViewSet(NetBoxModelViewSet): class DeviceRoleViewSet(NetBoxModelViewSet):
queryset = DeviceRole.objects.all() queryset = DeviceRole.objects.add_related_count(
DeviceRole.objects.add_related_count(
DeviceRole.objects.all(),
VirtualMachine,
'role',
'virtualmachine_count',
cumulative=True
),
Device,
'role',
'device_count',
cumulative=True
)
serializer_class = serializers.DeviceRoleSerializer serializer_class = serializers.DeviceRoleSerializer
filterset_class = filtersets.DeviceRoleFilterSet filterset_class = filtersets.DeviceRoleFilterSet

View File

@ -1990,9 +1990,18 @@ class InventoryItemTemplateBulkDeleteView(generic.BulkDeleteView):
@register_model_view(DeviceRole, 'list', path='', detail=False) @register_model_view(DeviceRole, 'list', path='', detail=False)
class DeviceRoleListView(generic.ObjectListView): class DeviceRoleListView(generic.ObjectListView):
queryset = DeviceRole.objects.annotate( queryset = DeviceRole.objects.add_related_count(
device_count=count_related(Device, 'role'), DeviceRole.objects.add_related_count(
vm_count=count_related(VirtualMachine, 'role') DeviceRole.objects.all(),
VirtualMachine,
'role',
'vm_count',
cumulative=True
),
Device,
'role',
'device_count',
cumulative=True
) )
filterset = filtersets.DeviceRoleFilterSet filterset = filtersets.DeviceRoleFilterSet
filterset_form = forms.DeviceRoleFilterForm filterset_form = forms.DeviceRoleFilterForm