Jeremy Stretch 6 лет назад
Родитель
Сommit
803287a514

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

@@ -7,6 +7,7 @@
 ## API Changes
 
 * dcim.Rack: The `/api/dcim/racks/<pk>/units/` endpoint has been replaced with `/api/dcim/racks/<pk>/elevation/`.
+* The `id__in` filter has been removed. Use the format `?id=1&id=2` instead. ([#4313](https://github.com/netbox-community/netbox/issues/4313))
 
 ## Other Changes
 

+ 1 - 9
netbox/circuits/filters.py

@@ -5,7 +5,7 @@ from dcim.models import Region, Site
 from extras.filters import CustomFieldFilterSet, CreatedUpdatedFilterSet
 from tenancy.filters import TenancyFilterSet
 from utilities.filters import (
-    BaseFilterSet, NameSlugSearchFilterSet, NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter
+    BaseFilterSet, NameSlugSearchFilterSet, TagFilter, TreeNodeMultipleChoiceFilter
 )
 from .choices import *
 from .models import Circuit, CircuitTermination, CircuitType, Provider
@@ -19,10 +19,6 @@ __all__ = (
 
 
 class ProviderFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',
@@ -77,10 +73,6 @@ class CircuitTypeFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
 
 
 class CircuitFilterSet(BaseFilterSet, CustomFieldFilterSet, TenancyFilterSet, CreatedUpdatedFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',

+ 0 - 10
netbox/circuits/tests/test_filters.py

@@ -70,11 +70,6 @@ class ProviderTestCase(TestCase):
         params = {'account': ['1234', '2345']}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
-    def test_id__in(self):
-        id_list = self.queryset.values_list('id', flat=True)[:3]
-        params = {'id__in': ','.join([str(id) for id in id_list])}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
-
     def test_site(self):
         sites = Site.objects.all()[:2]
         params = {'site_id': [sites[0].pk, sites[1].pk]}
@@ -194,11 +189,6 @@ class CircuitTestCase(TestCase):
         params = {'commit_rate': ['1000', '2000']}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
-    def test_id__in(self):
-        id_list = self.queryset.values_list('id', flat=True)[:3]
-        params = {'id__in': ','.join([str(id) for id in id_list])}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
-
     def test_provider(self):
         provider = Provider.objects.first()
         params = {'provider_id': [provider.pk]}

+ 1 - 29
netbox/dcim/filters.py

@@ -7,7 +7,7 @@ from tenancy.models import Tenant
 from utilities.constants import COLOR_CHOICES
 from utilities.filters import (
     BaseFilterSet, MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter,
-    NameSlugSearchFilterSet, NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter,
+    NameSlugSearchFilterSet, TagFilter, TreeNodeMultipleChoiceFilter,
 )
 from virtualization.models import Cluster
 from .choices import *
@@ -78,10 +78,6 @@ class RegionFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
 
 
 class SiteFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',
@@ -171,10 +167,6 @@ class RackRoleFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
 
 
 class RackFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',
@@ -251,10 +243,6 @@ class RackFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, Creat
 
 
 class RackReservationFilterSet(BaseFilterSet, TenancyFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',
@@ -319,10 +307,6 @@ class ManufacturerFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
 
 
 class DeviceTypeFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',
@@ -504,10 +488,6 @@ class DeviceFilterSet(
     CustomFieldFilterSet,
     CreatedUpdatedFilterSet
 ):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',
@@ -1236,10 +1216,6 @@ class InterfaceConnectionFilterSet(BaseFilterSet):
 
 
 class PowerPanelFilterSet(BaseFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',
@@ -1287,10 +1263,6 @@ class PowerPanelFilterSet(BaseFilterSet):
 
 
 class PowerFeedFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',

+ 0 - 25
netbox/dcim/tests/test_filters.py

@@ -138,11 +138,6 @@ class SiteTestCase(TestCase):
         params = {'contact_email': ['contact1@example.com', 'contact2@example.com']}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
-    def test_id__in(self):
-        id_list = self.queryset.values_list('id', flat=True)[:2]
-        params = {'id__in': ','.join([str(id) for id in id_list])}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
-
     def test_status(self):
         params = {'status': [SiteStatusChoices.STATUS_ACTIVE, SiteStatusChoices.STATUS_PLANNED]}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
@@ -365,11 +360,6 @@ class RackTestCase(TestCase):
         params = {'outer_unit': RackDimensionUnitChoices.UNIT_MILLIMETER}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
-    def test_id__in(self):
-        id_list = self.queryset.values_list('id', flat=True)[:2]
-        params = {'id__in': ','.join([str(id) for id in id_list])}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
-
     def test_region(self):
         regions = Region.objects.all()[:2]
         params = {'region_id': [regions[0].pk, regions[1].pk]}
@@ -479,11 +469,6 @@ class RackReservationTestCase(TestCase):
         )
         RackReservation.objects.bulk_create(reservations)
 
-    def test_id__in(self):
-        id_list = self.queryset.values_list('id', flat=True)[:2]
-        params = {'id__in': ','.join([str(id) for id in id_list])}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
-
     def test_site(self):
         sites = Site.objects.all()[:2]
         params = {'site_id': [sites[0].pk, sites[1].pk]}
@@ -631,11 +616,6 @@ class DeviceTypeTestCase(TestCase):
         params = {'subdevice_role': SubdeviceRoleChoices.ROLE_PARENT}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
 
-    def test_id__in(self):
-        id_list = self.queryset.values_list('id', flat=True)[:2]
-        params = {'id__in': ','.join([str(id) for id in id_list])}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
-
     def test_manufacturer(self):
         manufacturers = Manufacturer.objects.all()[:2]
         params = {'manufacturer_id': [manufacturers[0].pk, manufacturers[1].pk]}
@@ -1283,11 +1263,6 @@ class DeviceTestCase(TestCase):
         params = {'vc_priority': [1, 2]}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
-    def test_id__in(self):
-        id_list = self.queryset.values_list('id', flat=True)[:2]
-        params = {'id__in': ','.join([str(id) for id in id_list])}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
-
     def test_manufacturer(self):
         manufacturers = Manufacturer.objects.all()[:2]
         params = {'manufacturer_id': [manufacturers[0].pk, manufacturers[1].pk]}

+ 2 - 26
netbox/ipam/filters.py

@@ -8,8 +8,8 @@ from dcim.models import Device, Interface, Region, Site
 from extras.filters import CustomFieldFilterSet, CreatedUpdatedFilterSet
 from tenancy.filters import TenancyFilterSet
 from utilities.filters import (
-    BaseFilterSet, MultiValueCharFilter, MultiValueNumberFilter, NameSlugSearchFilterSet,
-    NumericInFilter, TagFilter, TreeNodeMultipleChoiceFilter,
+    BaseFilterSet, MultiValueCharFilter, MultiValueNumberFilter, NameSlugSearchFilterSet, TagFilter,
+    TreeNodeMultipleChoiceFilter,
 )
 from virtualization.models import VirtualMachine
 from .choices import *
@@ -30,10 +30,6 @@ __all__ = (
 
 
 class VRFFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',
@@ -55,10 +51,6 @@ class VRFFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, Create
 
 
 class RIRFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
 
     class Meta:
         model = RIR
@@ -66,10 +58,6 @@ class RIRFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
 
 
 class AggregateFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',
@@ -131,10 +119,6 @@ class RoleFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
 
 
 class PrefixFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',
@@ -285,10 +269,6 @@ class PrefixFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, Cre
 
 
 class IPAddressFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',
@@ -443,10 +423,6 @@ class VLANGroupFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
 
 
 class VLANFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',

+ 0 - 25
netbox/ipam/tests/test_filters.py

@@ -53,11 +53,6 @@ class VRFTestCase(TestCase):
         params = {'enforce_unique': 'false'}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
 
-    def test_id__in(self):
-        id_list = self.queryset.values_list('id', flat=True)[:3]
-        params = {'id__in': ','.join([str(id) for id in id_list])}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
-
     def test_tenant(self):
         tenants = Tenant.objects.all()[:2]
         params = {'tenant_id': [tenants[0].pk, tenants[1].pk]}
@@ -104,11 +99,6 @@ class RIRTestCase(TestCase):
         params = {'is_private': 'false'}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
 
-    def test_id__in(self):
-        id_list = self.queryset.values_list('id', flat=True)[:3]
-        params = {'id__in': ','.join([str(id) for id in id_list])}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
-
 
 class AggregateTestCase(TestCase):
     queryset = Aggregate.objects.all()
@@ -265,11 +255,6 @@ class PrefixTestCase(TestCase):
         params = {'is_pool': 'false'}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 8)
 
-    def test_id__in(self):
-        id_list = self.queryset.values_list('id', flat=True)[:3]
-        params = {'id__in': ','.join([str(id) for id in id_list])}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
-
     def test_within(self):
         params = {'within': '10.0.0.0/16'}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4)
@@ -425,11 +410,6 @@ class IPAddressTestCase(TestCase):
         params = {'dns_name': ['ipaddress-a', 'ipaddress-b']}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4)
 
-    def test_id__in(self):
-        id_list = self.queryset.values_list('id', flat=True)[:3]
-        params = {'id__in': ','.join([str(id) for id in id_list])}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
-
     def test_parent(self):
         params = {'parent': '10.0.0.0/24'}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 5)
@@ -640,11 +620,6 @@ class VLANTestCase(TestCase):
         params = {'vid': ['101', '201', '301']}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
 
-    def test_id__in(self):
-        id_list = self.queryset.values_list('id', flat=True)[:3]
-        params = {'id__in': ','.join([str(id) for id in id_list])}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
-
     def test_region(self):
         regions = Region.objects.all()[:2]
         params = {'region_id': [regions[0].pk, regions[1].pk]}

+ 0 - 1
netbox/netbox/settings.py

@@ -522,7 +522,6 @@ SWAGGER_SETTINGS = {
         'drf_yasg.inspectors.StringDefaultFieldInspector',
     ],
     'DEFAULT_FILTER_INSPECTORS': [
-        'utilities.custom_inspectors.IdInFilterInspector',
         'drf_yasg.inspectors.CoreAPICompatInspector',
     ],
     'DEFAULT_INFO': 'netbox.urls.openapi_info',

+ 1 - 5
netbox/secrets/filters.py

@@ -3,7 +3,7 @@ from django.db.models import Q
 
 from dcim.models import Device
 from extras.filters import CustomFieldFilterSet, CreatedUpdatedFilterSet
-from utilities.filters import BaseFilterSet, NameSlugSearchFilterSet, NumericInFilter, TagFilter
+from utilities.filters import BaseFilterSet, NameSlugSearchFilterSet, TagFilter
 from .models import Secret, SecretRole
 
 
@@ -21,10 +21,6 @@ class SecretRoleFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
 
 
 class SecretFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',

+ 0 - 5
netbox/secrets/tests/test_filters.py

@@ -72,11 +72,6 @@ class SecretTestCase(TestCase):
         params = {'name': ['Secret 1', 'Secret 2']}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
-    def test_id__in(self):
-        id_list = self.queryset.values_list('id', flat=True)[:2]
-        params = {'id__in': ','.join([str(id) for id in id_list])}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
-
     def test_role(self):
         roles = SecretRole.objects.all()[:2]
         params = {'role_id': [roles[0].pk, roles[1].pk]}

+ 1 - 5
netbox/tenancy/filters.py

@@ -2,7 +2,7 @@ import django_filters
 from django.db.models import Q
 
 from extras.filters import CustomFieldFilterSet, CreatedUpdatedFilterSet
-from utilities.filters import BaseFilterSet, NameSlugSearchFilterSet, NumericInFilter, TagFilter
+from utilities.filters import BaseFilterSet, NameSlugSearchFilterSet, TagFilter
 from .models import Tenant, TenantGroup
 
 
@@ -21,10 +21,6 @@ class TenantGroupFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
 
 
 class TenantFilterSet(BaseFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',

+ 0 - 5
netbox/tenancy/tests/test_filters.py

@@ -61,11 +61,6 @@ class TenantTestCase(TestCase):
         params = {'slug': ['tenant-1', 'tenant-2']}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
-    def test_id__in(self):
-        id_list = self.queryset.values_list('id', flat=True)[:2]
-        params = {'id__in': ','.join([str(id) for id in id_list])}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
-
     def test_group(self):
         group = TenantGroup.objects.all()[:2]
         params = {'group_id': [group[0].pk, group[1].pk]}

+ 0 - 10
netbox/utilities/custom_inspectors.py

@@ -131,16 +131,6 @@ class JSONFieldInspector(FieldInspector):
         return result
 
 
-class IdInFilterInspector(FilterInspector):
-    def process_result(self, result, method_name, obj, **kwargs):
-        if isinstance(result, list):
-            params = [p for p in result if isinstance(p, openapi.Parameter) and p.name == 'id__in']
-            for p in params:
-                p.type = 'string'
-
-        return result
-
-
 class NullablePaginatorInspector(PaginatorInspector):
     def process_result(self, result, method_name, obj, **kwargs):
         if method_name == 'get_paginated_response' and isinstance(result, openapi.Schema):

+ 0 - 7
netbox/utilities/filters.py

@@ -80,13 +80,6 @@ class TreeNodeMultipleChoiceFilter(django_filters.ModelMultipleChoiceFilter):
         return super().filter(qs, value)
 
 
-class NumericInFilter(django_filters.BaseInFilter, django_filters.NumberFilter):
-    """
-    Filters for a set of numeric values. Example: id__in=100,200,300
-    """
-    pass
-
-
 class NullableCharFieldFilter(django_filters.CharFilter):
     """
     Allow matching on null field values by passing a special string used to signify NULL.

+ 1 - 10
netbox/virtualization/filters.py

@@ -4,9 +4,8 @@ from django.db.models import Q
 from dcim.models import DeviceRole, Interface, Platform, Region, Site
 from extras.filters import CustomFieldFilterSet, CreatedUpdatedFilterSet, LocalConfigContextFilterSet
 from tenancy.filters import TenancyFilterSet
-from tenancy.models import Tenant
 from utilities.filters import (
-    BaseFilterSet, MultiValueMACAddressFilter, NameSlugSearchFilterSet, NumericInFilter, TagFilter,
+    BaseFilterSet, MultiValueMACAddressFilter, NameSlugSearchFilterSet, TagFilter,
     TreeNodeMultipleChoiceFilter,
 )
 from .choices import *
@@ -36,10 +35,6 @@ class ClusterGroupFilterSet(BaseFilterSet, NameSlugSearchFilterSet):
 
 
 class ClusterFilterSet(BaseFilterSet, TenancyFilterSet, CustomFieldFilterSet, CreatedUpdatedFilterSet):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',
@@ -109,10 +104,6 @@ class VirtualMachineFilterSet(
     CustomFieldFilterSet,
     CreatedUpdatedFilterSet
 ):
-    id__in = NumericInFilter(
-        field_name='id',
-        lookup_expr='in'
-    )
     q = django_filters.CharFilter(
         method='search',
         label='Search',

+ 0 - 10
netbox/virtualization/tests/test_filters.py

@@ -125,11 +125,6 @@ class ClusterTestCase(TestCase):
         params = {'name': ['Cluster 1', 'Cluster 2']}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
-    def test_id__in(self):
-        id_list = self.queryset.values_list('id', flat=True)[:2]
-        params = {'id__in': ','.join([str(id) for id in id_list])}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
-
     def test_region(self):
         regions = Region.objects.all()[:2]
         params = {'region_id': [regions[0].pk, regions[1].pk]}
@@ -280,11 +275,6 @@ class VirtualMachineTestCase(TestCase):
         params = {'disk': [1, 2]}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
 
-    def test_id__in(self):
-        id_list = self.queryset.values_list('id', flat=True)[:2]
-        params = {'id__in': ','.join([str(id) for id in id_list])}
-        self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)
-
     def test_status(self):
         params = {'status': [VirtualMachineStatusChoices.STATUS_ACTIVE, VirtualMachineStatusChoices.STATUS_STAGED]}
         self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)