From 7195f51c6cd66a1f12c917251b25bca3a0f2b676 Mon Sep 17 00:00:00 2001 From: Brian Tiemann Date: Fri, 13 Sep 2024 08:52:17 -0400 Subject: [PATCH] Change to EmptyStringMultipleChoiceFilter --- netbox/dcim/choices.py | 10 ++++++++-- netbox/dcim/filtersets.py | 7 ++----- netbox/dcim/tests/test_filtersets.py | 8 +++----- netbox/utilities/filters.py | 14 ++++++-------- 4 files changed, 19 insertions(+), 20 deletions(-) diff --git a/netbox/dcim/choices.py b/netbox/dcim/choices.py index 127655ba7..253f483e7 100644 --- a/netbox/dcim/choices.py +++ b/netbox/dcim/choices.py @@ -1470,6 +1470,7 @@ class CableTypeChoices(ChoiceSet): TYPE_AOC = 'aoc' TYPE_POWER = 'power' TYPE_USB = 'usb' + TYPE_EMPTY = 'EMPTY' CHOICES = ( ( @@ -1502,8 +1503,13 @@ class CableTypeChoices(ChoiceSet): (TYPE_AOC, 'Active Optical Cabling (AOC)'), ), ), - (TYPE_USB, _('USB')), - (TYPE_POWER, _('Power')), + ( + _('Other'), ( + (TYPE_USB, _('USB')), + (TYPE_POWER, _('Power')), + (TYPE_EMPTY, _('(unset)')), + ) + ) ) diff --git a/netbox/dcim/filtersets.py b/netbox/dcim/filtersets.py index 183c80299..419769ce8 100644 --- a/netbox/dcim/filtersets.py +++ b/netbox/dcim/filtersets.py @@ -18,7 +18,7 @@ from tenancy.models import * from users.models import User from utilities.filters import ( ContentTypeFilter, MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter, MultiValueWWNFilter, - NumericArrayFilter, TreeNodeMultipleChoiceFilter, EmptyStringFilter, + NumericArrayFilter, TreeNodeMultipleChoiceFilter, EmptyStringMultipleChoiceFilter, ) from virtualization.models import Cluster, ClusterGroup from vpn.models import L2VPN @@ -1980,12 +1980,9 @@ class CableFilterSet(TenancyFilterSet, NetBoxModelFilterSet): method='_unterminated', label=_('Unterminated'), ) - type = django_filters.MultipleChoiceFilter( + type = EmptyStringMultipleChoiceFilter( choices=CableTypeChoices ) - type__empty = EmptyStringFilter( - field_name='type' - ) status = django_filters.MultipleChoiceFilter( choices=LinkStatusChoices ) diff --git a/netbox/dcim/tests/test_filtersets.py b/netbox/dcim/tests/test_filtersets.py index b93939d33..182013867 100644 --- a/netbox/dcim/tests/test_filtersets.py +++ b/netbox/dcim/tests/test_filtersets.py @@ -5247,12 +5247,10 @@ class CableTestCase(TestCase, ChangeLoggedFilterSetTests): def test_type(self): params = {'type': [CableTypeChoices.TYPE_CAT3, CableTypeChoices.TYPE_CAT5E]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4) - - def test_type_empty(self): - params = {'type__empty': 'true'} + params = {'type': [CableTypeChoices.TYPE_EMPTY]} self.assertEqual(self.filterset(params, self.queryset).qs.count(), 8) - params = {'type__empty': 'false'} - self.assertEqual(self.filterset(params, self.queryset).qs.count(), 6) + params = {'type': [CableTypeChoices.TYPE_EMPTY, CableTypeChoices.TYPE_CAT3]} + self.assertEqual(self.filterset(params, self.queryset).qs.count(), 10) def test_status(self): params = {'status': [LinkStatusChoices.STATUS_CONNECTED]} diff --git a/netbox/utilities/filters.py b/netbox/utilities/filters.py index 95c615dcb..3d8203b85 100644 --- a/netbox/utilities/filters.py +++ b/netbox/utilities/filters.py @@ -173,12 +173,10 @@ class ContentTypeFilter(django_filters.CharFilter): ) -class EmptyStringFilter(django_filters.BooleanFilter): +class EmptyStringMultipleChoiceFilter(django_filters.MultipleChoiceFilter): + empty_value = 'EMPTY' + def filter(self, qs, value): - if value in EMPTY_VALUES: - return qs - - exclude = self.exclude ^ (value is False) - method = qs.exclude if exclude else qs.filter - - return method(**{self.field_name: ""}) + if self.empty_value in value: + value.append('') + return super().filter(qs, value)