diff --git a/docs/release-notes/version-2.7.md b/docs/release-notes/version-2.7.md index 123199582..760dd21d9 100644 --- a/docs/release-notes/version-2.7.md +++ b/docs/release-notes/version-2.7.md @@ -3,6 +3,7 @@ ## Enhancements * [#3842](https://github.com/netbox-community/netbox/issues/3842) - Add 802.11ax interface type +* [#3954](https://github.com/netbox-community/netbox/issues/3954) - Add `device_bays` filter for devices and device types ## Bug Fixes diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index cf100af00..d749e28c6 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -1,6 +1,5 @@ import django_filters from django.contrib.auth.models import User -from django.db.models import Q from extras.filters import CustomFieldFilterSet, LocalConfigContextFilterSet, CreatedUpdatedFilterSet from tenancy.filters import TenancyFilterSet @@ -356,6 +355,10 @@ class DeviceTypeFilterSet(CustomFieldFilterSet, CreatedUpdatedFilterSet): method='_pass_through_ports', label='Has pass-through ports', ) + device_bays = django_filters.BooleanFilter( + method='_device_bays', + label='Has device bays', + ) tag = TagFilter() class Meta: @@ -395,6 +398,9 @@ class DeviceTypeFilterSet(CustomFieldFilterSet, CreatedUpdatedFilterSet): rearport_templates__isnull=value ) + def _device_bays(self, queryset, name, value): + return queryset.exclude(device_bay_templates__isnull=value) + class DeviceTypeComponentFilterSet(NameSlugSearchFilterSet): devicetype_id = django_filters.ModelMultipleChoiceFilter( @@ -623,6 +629,10 @@ class DeviceFilterSet(LocalConfigContextFilterSet, TenancyFilterSet, CustomField method='_pass_through_ports', label='Has pass-through ports', ) + device_bays = django_filters.BooleanFilter( + method='_device_bays', + label='Has device bays', + ) tag = TagFilter() class Meta: @@ -676,6 +686,9 @@ class DeviceFilterSet(LocalConfigContextFilterSet, TenancyFilterSet, CustomField rearports__isnull=value ) + def _device_bays(self, queryset, name, value): + return queryset.exclude(device_bays__isnull=value) + class DeviceComponentFilterSet(django_filters.FilterSet): q = django_filters.CharFilter( diff --git a/netbox/dcim/tests/test_filters.py b/netbox/dcim/tests/test_filters.py index 0c3206cd7..03d7d0bfa 100644 --- a/netbox/dcim/tests/test_filters.py +++ b/netbox/dcim/tests/test_filters.py @@ -595,12 +595,11 @@ class DeviceTypeTestCase(TestCase): params = {'pass_through_ports': 'false'} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) - # TODO: Add device_bay filter - # def test_device_bays(self): - # params = {'device_bays': 'true'} - # self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) - # params = {'device_bays': 'false'} - # self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + def test_device_bays(self): + params = {'device_bays': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'device_bays': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) class ConsolePortTemplateTestCase(TestCase): @@ -1322,12 +1321,11 @@ class DeviceTestCase(TestCase): params = {'pass_through_ports': 'false'} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) - # TODO: Add device_bay filter - # def test_device_bays(self): - # params = {'device_bays': 'true'} - # self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) - # params = {'device_bays': 'false'} - # self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) + def test_device_bays(self): + params = {'device_bays': 'true'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2) + params = {'device_bays': 'false'} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1) def test_local_context_data(self): params = {'local_context_data': 'true'}