Skip to content

Commit 39256af

Browse files
committed
Closes #7394: Enable filtering cables by termination type & ID in REST API
1 parent 69aaf28 commit 39256af

File tree

3 files changed

+35
-11
lines changed

3 files changed

+35
-11
lines changed

docs/release-notes/version-3.0.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
* [#6850](https://github.com/netbox-community/netbox/issues/6850) - Default to current user when creating journal entries via REST API
88
* [#6955](https://github.com/netbox-community/netbox/issues/6955) - Include type, ID, and slug on object view
9+
* [#7394](https://github.com/netbox-community/netbox/issues/7394) - Enable filtering cables by termination type & ID in REST API
910
* [#7462](https://github.com/netbox-community/netbox/issues/7462) - Include count of assigned virtual machines under platform view
1011

1112
### Bug Fixes

netbox/dcim/filtersets.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@
1010
from tenancy.models import Tenant
1111
from utilities.choices import ColorChoices
1212
from utilities.filters import (
13-
MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter, TreeNodeMultipleChoiceFilter,
13+
ContentTypeFilter, MultiValueCharFilter, MultiValueMACAddressFilter, MultiValueNumberFilter,
14+
TreeNodeMultipleChoiceFilter,
1415
)
1516
from virtualization.models import Cluster
1617
from .choices import *
@@ -1183,6 +1184,10 @@ class CableFilterSet(PrimaryModelFilterSet):
11831184
method='search',
11841185
label='Search',
11851186
)
1187+
termination_a_type = ContentTypeFilter()
1188+
termination_a_id = MultiValueNumberFilter()
1189+
termination_b_type = ContentTypeFilter()
1190+
termination_b_id = MultiValueNumberFilter()
11861191
type = django_filters.MultipleChoiceFilter(
11871192
choices=CableTypeChoices
11881193
)
@@ -1227,7 +1232,7 @@ class CableFilterSet(PrimaryModelFilterSet):
12271232

12281233
class Meta:
12291234
model = Cable
1230-
fields = ['id', 'label', 'length', 'length_unit']
1235+
fields = ['id', 'label', 'length', 'length_unit', 'termination_a_id', 'termination_b_id']
12311236

12321237
def search(self, queryset, name, value):
12331238
if not value.strip():

netbox/dcim/tests/test_filtersets.py

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2851,13 +2851,17 @@ def setUpTestData(cls):
28512851
)
28522852
Interface.objects.bulk_create(interfaces)
28532853

2854+
console_port = ConsolePort.objects.create(device=devices[0], name='Console Port 1')
2855+
console_server_port = ConsoleServerPort.objects.create(device=devices[0], name='Console Server Port 1')
2856+
28542857
# Cables
28552858
Cable(termination_a=interfaces[1], termination_b=interfaces[2], label='Cable 1', type=CableTypeChoices.TYPE_CAT3, status=CableStatusChoices.STATUS_CONNECTED, color='aa1409', length=10, length_unit=CableLengthUnitChoices.UNIT_FOOT).save()
28562859
Cable(termination_a=interfaces[3], termination_b=interfaces[4], label='Cable 2', type=CableTypeChoices.TYPE_CAT3, status=CableStatusChoices.STATUS_CONNECTED, color='aa1409', length=20, length_unit=CableLengthUnitChoices.UNIT_FOOT).save()
28572860
Cable(termination_a=interfaces[5], termination_b=interfaces[6], label='Cable 3', type=CableTypeChoices.TYPE_CAT5E, status=CableStatusChoices.STATUS_CONNECTED, color='f44336', length=30, length_unit=CableLengthUnitChoices.UNIT_FOOT).save()
28582861
Cable(termination_a=interfaces[7], termination_b=interfaces[8], label='Cable 4', type=CableTypeChoices.TYPE_CAT5E, status=CableStatusChoices.STATUS_PLANNED, color='f44336', length=40, length_unit=CableLengthUnitChoices.UNIT_FOOT).save()
28592862
Cable(termination_a=interfaces[9], termination_b=interfaces[10], label='Cable 5', type=CableTypeChoices.TYPE_CAT6, status=CableStatusChoices.STATUS_PLANNED, color='e91e63', length=10, length_unit=CableLengthUnitChoices.UNIT_METER).save()
28602863
Cable(termination_a=interfaces[11], termination_b=interfaces[0], label='Cable 6', type=CableTypeChoices.TYPE_CAT6, status=CableStatusChoices.STATUS_PLANNED, color='e91e63', length=20, length_unit=CableLengthUnitChoices.UNIT_METER).save()
2864+
Cable(termination_a=console_port, termination_b=console_server_port, label='Cable 7').save()
28612865

28622866
def test_label(self):
28632867
params = {'label': ['Cable 1', 'Cable 2']}
@@ -2877,7 +2881,7 @@ def test_type(self):
28772881

28782882
def test_status(self):
28792883
params = {'status': [CableStatusChoices.STATUS_CONNECTED]}
2880-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
2884+
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4)
28812885
params = {'status': [CableStatusChoices.STATUS_PLANNED]}
28822886
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
28832887

@@ -2888,30 +2892,44 @@ def test_color(self):
28882892
def test_device(self):
28892893
devices = Device.objects.all()[:2]
28902894
params = {'device_id': [devices[0].pk, devices[1].pk]}
2891-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
2895+
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4)
28922896
params = {'device': [devices[0].name, devices[1].name]}
2893-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
2897+
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4)
28942898

28952899
def test_rack(self):
28962900
racks = Rack.objects.all()[:2]
28972901
params = {'rack_id': [racks[0].pk, racks[1].pk]}
2898-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 5)
2902+
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 6)
28992903
params = {'rack': [racks[0].name, racks[1].name]}
2900-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 5)
2904+
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 6)
29012905

29022906
def test_site(self):
29032907
site = Site.objects.all()[:2]
29042908
params = {'site_id': [site[0].pk, site[1].pk]}
2905-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 5)
2909+
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 6)
29062910
params = {'site': [site[0].slug, site[1].slug]}
2907-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 5)
2911+
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 6)
29082912

29092913
def test_tenant(self):
29102914
tenant = Tenant.objects.all()[:2]
29112915
params = {'tenant_id': [tenant[0].pk, tenant[1].pk]}
2912-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4)
2916+
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 5)
29132917
params = {'tenant': [tenant[0].slug, tenant[1].slug]}
2914-
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 4)
2918+
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 5)
2919+
2920+
def test_termination_types(self):
2921+
params = {'termination_a_type': 'dcim.consoleport'}
2922+
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
2923+
params = {'termination_b_type': 'dcim.consoleserverport'}
2924+
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)
2925+
2926+
def test_termination_ids(self):
2927+
interface_ids = Cable.objects.values_list('termination_a_id', flat=True)[:3]
2928+
params = {
2929+
'termination_a_type': 'dcim.interface',
2930+
'termination_a_id': list(interface_ids),
2931+
}
2932+
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 3)
29152933

29162934

29172935
class PowerPanelTestCase(TestCase, ChangeLoggedFilterSetTests):

0 commit comments

Comments
 (0)