Forráskód Böngészése

Fixes #9705: Support filter expressions for the serial field on racks, devices, and inventory items

jeremystretch 3 éve
szülő
commit
17e00ac040

+ 1 - 0
docs/release-notes/version-3.2.md

@@ -4,6 +4,7 @@
 
 ### Enhancements
 
+* [#9705](https://github.com/netbox-community/netbox/issues/9705) - Support filter expressions for the `serial` field on racks, devices, and inventory items
 * [#9741](https://github.com/netbox-community/netbox/issues/9741) - Check for UserConfig instance during user login
 * [#9745](https://github.com/netbox-community/netbox/issues/9745) - Add wireless LANs and links to global search
 

+ 6 - 3
netbox/dcim/filtersets.py

@@ -307,7 +307,7 @@ class RackFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSe
         to_field_name='slug',
         label='Role (slug)',
     )
-    serial = django_filters.CharFilter(
+    serial = MultiValueCharFilter(
         lookup_expr='iexact'
     )
 
@@ -1002,10 +1002,13 @@ class ModuleFilterSet(NetBoxModelFilterSet):
         queryset=Device.objects.all(),
         label='Device (ID)',
     )
+    serial = MultiValueCharFilter(
+        lookup_expr='iexact'
+    )
 
     class Meta:
         model = Module
-        fields = ['id', 'serial', 'asset_tag']
+        fields = ['id', 'asset_tag']
 
     def search(self, queryset, name, value):
         if not value.strip():
@@ -1400,7 +1403,7 @@ class InventoryItemFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
     )
     component_type = ContentTypeFilter()
     component_id = MultiValueNumberFilter()
-    serial = django_filters.CharFilter(
+    serial = MultiValueCharFilter(
         lookup_expr='iexact'
     )
 

+ 11 - 9
netbox/dcim/tests/test_filtersets.py

@@ -494,10 +494,10 @@ class RackTestCase(TestCase, ChangeLoggedFilterSetTests):
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
     def test_serial(self):
-        params = {'serial': 'ABC'}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
-        params = {'serial': 'abc'}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
+        params = {'serial': ['ABC', 'DEF']}
+        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
+        params = {'serial': ['abc', 'def']}
+        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
     def test_tenant(self):
         tenants = Tenant.objects.all()[:2]
@@ -1860,7 +1860,9 @@ class ModuleTestCase(TestCase, ChangeLoggedFilterSetTests):
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 6)
 
     def test_serial(self):
-        params = {'asset_tag': ['A', 'B']}
+        params = {'serial': ['A', 'B']}
+        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
+        params = {'serial': ['a', 'b']}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
     def test_asset_tag(self):
@@ -3413,10 +3415,10 @@ class InventoryItemTestCase(TestCase, ChangeLoggedFilterSetTests):
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
     def test_serial(self):
-        params = {'serial': 'ABC'}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
-        params = {'serial': 'abc'}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
+        params = {'serial': ['ABC', 'DEF']}
+        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
+        params = {'serial': ['abc', 'def']}
+        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
     def test_component_type(self):
         params = {'component_type': 'dcim.interface'}

+ 1 - 1
netbox/netbox/filtersets.py

@@ -125,7 +125,7 @@ class BaseFilterSet(django_filters.FilterSet):
             return {}
 
         # Skip nonstandard lookup expressions
-        if existing_filter.method is not None or existing_filter.lookup_expr not in ['exact', 'in']:
+        if existing_filter.method is not None or existing_filter.lookup_expr not in ['exact', 'iexact', 'in']:
             return {}
 
         # Choose the lookup expression map based on the filter type