Closes #4313: Remove id__in filters

This commit is contained in:
Jeremy Stretch 2020-03-06 12:05:53 -05:00
parent 1a89e35729
commit 803287a514
16 changed files with 8 additions and 182 deletions

View File

@ -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

View File

@ -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',

View File

@ -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]}

View File

@ -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',

View File

@ -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]}

View File

@ -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',

View File

@ -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]}

View File

@ -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',

View File

@ -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',

View File

@ -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]}

View File

@ -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',

View File

@ -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]}

View File

@ -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):

View File

@ -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.

View File

@ -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',

View File

@ -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)