diff --git a/CHANGELOG.md b/CHANGELOG.md index c7ec8b446..d02babd3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ v2.6.2 (FUTURE) ## Bug Fixes +* [#3293](https://github.com/netbox-community/netbox/issues/3293) - Enable filtering device components by multiple device IDs * [#3317](https://github.com/netbox-community/netbox/issues/3317) - Fix permissions for ConfigContextBulkDeleteView * [#3323](https://github.com/netbox-community/netbox/issues/3323) - Fix permission evaluation for interface connections view * [#3342](https://github.com/netbox-community/netbox/issues/3342) - Fix cluster delete button diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index 6312fd0d5..911f3c0a3 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -9,7 +9,9 @@ from extras.filters import CustomFieldFilterSet from tenancy.filtersets import TenancyFilterSet from tenancy.models import Tenant from utilities.constants import COLOR_CHOICES -from utilities.filters import NameSlugSearchFilterSet, NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter +from utilities.filters import ( + MultiValueNumberFilter, NameSlugSearchFilterSet, NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter, +) from virtualization.models import Cluster from .constants import * from .models import ( @@ -624,7 +626,7 @@ class DeviceComponentFilterSet(django_filters.FilterSet): method='search', label='Search', ) - device_id = django_filters.ModelChoiceFilter( + device_id = django_filters.ModelMultipleChoiceFilter( queryset=Device.objects.all(), label='Device (ID)', ) @@ -705,8 +707,8 @@ class InterfaceFilter(django_filters.FilterSet): field_name='name', label='Device', ) - device_id = django_filters.NumberFilter( - method='filter_device', + device_id = MultiValueNumberFilter( + method='filter_device_id', field_name='pk', label='Device (ID)', ) @@ -762,6 +764,17 @@ class InterfaceFilter(django_filters.FilterSet): except Device.DoesNotExist: return queryset.none() + def filter_device_id(self, queryset, name, id_list): + # Include interfaces belonging to peer virtual chassis members + vc_interface_ids = [] + try: + devices = Device.objects.filter(pk__in=id_list) + for device in devices: + vc_interface_ids += device.vc_interfaces.values_list('id', flat=True) + return queryset.filter(pk__in=vc_interface_ids) + except Device.DoesNotExist: + return queryset.none() + def filter_vlan_id(self, queryset, name, value): value = value.strip() if not value: