Skip to content

Commit

Permalink
Update filtersets (#227)
Browse files Browse the repository at this point in the history
* fix 226: add q method on PeeringFilterSet

* fix 192: change q search method for SearchFilter

* added search filter for AddressFamilyFilterSet

* Update changes/192.changed

Co-authored-by: Glenn Matthews <glenn.matthews@networktocode.com>

* Update changes/226.added

Co-authored-by: Glenn Matthews <glenn.matthews@networktocode.com>

* Delete changes/226.fixed

* replacing django TestCase by BaseFilterTestCase + search function for all filtersets tests

---------

Co-authored-by: Glenn Matthews <glenn.matthews@networktocode.com>
  • Loading branch information
pl0xym0r and glennmatthews authored Dec 16, 2024
1 parent e452a40 commit e4ba1f1
Show file tree
Hide file tree
Showing 4 changed files with 89 additions and 98 deletions.
1 change: 1 addition & 0 deletions changes/192.changed
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Changed all `q` search methods to use `SearchFilter`.
1 change: 1 addition & 0 deletions changes/226.added
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Added `q` search filters to `AddressFamilyFilterSet` and `PeeringFilterSet`.
142 changes: 56 additions & 86 deletions nautobot_bgp_models/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
"""FilterSet definitions for nautobot_bgp_models."""

import django_filters
from django.db.models import Q
from nautobot.apps.filters import (
BaseFilterSet,
CreatedUpdatedModelFilterSetMixin,
CustomFieldModelFilterSetMixin,
SearchFilter,
StatusModelFilterSetMixin,
)
from nautobot.dcim.models import Device
Expand All @@ -22,17 +22,13 @@ class AutonomousSystemFilterSet(
):
"""Filtering of AutonomousSystem records."""

q = django_filters.CharFilter(
method="search",
label="Search",
q = SearchFilter(
filter_predicates={
"asn": "icontains",
"description": "icontains",
},
)

def search(self, queryset, name, value): # pylint: disable=unused-argument
"""Free-text search method implementation."""
if not value.strip():
return queryset
return queryset.filter(Q(asn__icontains=value) | Q(description__icontains=value)).distinct()

class Meta:
model = models.AutonomousSystem
fields = ["id", "asn", "status", "tags"]
Expand All @@ -45,20 +41,15 @@ class AutonomousSystemRangeFilterSet(
):
"""Filtering of AutonomousSystemRange records."""

q = django_filters.CharFilter(
method="search",
label="Search",
q = SearchFilter(
filter_predicates={
"name": "icontains",
"asn_max": "icontains",
"asn_min": "icontains",
"description": "icontains",
},
)

def search(self, queryset, name, value): # pylint: disable=unused-argument
"""Free-text search method implementation."""
if not value.strip():
return queryset

return queryset.filter(
Q(name=value) | Q(asn_max__icontains=value) | Q(asn_min__icontains=value) | Q(description__icontains=value)
).distinct()

class Meta:
model = models.AutonomousSystemRange
fields = ["id", "name", "asn_min", "asn_max", "tags"]
Expand All @@ -69,9 +60,10 @@ class BGPRoutingInstanceFilterSet(
):
"""Filtering of BGPRoutingInstance records."""

q = django_filters.CharFilter(
method="search",
label="Search",
q = SearchFilter(
filter_predicates={
"device__name": "icontains",
},
)

autonomous_system = django_filters.ModelMultipleChoiceFilter(
Expand All @@ -97,19 +89,15 @@ class Meta:
model = models.BGPRoutingInstance
fields = ["id", "autonomous_system", "tags"]

def search(self, queryset, name, value): # pylint: disable=unused-argument
"""Free-text search method implementation."""
if not value.strip():
return queryset
return queryset.filter(Q(device__name__icontains=value)).distinct()


class PeerGroupFilterSet(RoleModelFilterSetMixin, BaseFilterSet):
"""Filtering of PeerGroup records."""

q = django_filters.CharFilter(
method="search",
label="Search",
q = SearchFilter(
filter_predicates={
"name": "icontains",
"description": "icontains",
},
)

autonomous_system = django_filters.ModelMultipleChoiceFilter(
Expand Down Expand Up @@ -144,19 +132,15 @@ class Meta:
model = models.PeerGroup
fields = ["id", "name", "enabled"]

def search(self, queryset, name, value): # pylint: disable=unused-argument
"""Free-text search method implementation."""
if not value.strip():
return queryset
return queryset.filter(Q(name__icontains=value) | Q(description__icontains=value)).distinct()


class PeerGroupTemplateFilterSet(RoleModelFilterSetMixin, BaseFilterSet):
"""Filtering of PeerGroupTemplate records."""

q = django_filters.CharFilter(
method="search",
label="Search",
q = SearchFilter(
filter_predicates={
"name": "icontains",
"description": "icontains",
},
)

autonomous_system = django_filters.ModelMultipleChoiceFilter(
Expand All @@ -170,19 +154,15 @@ class Meta:
model = models.PeerGroupTemplate
fields = ["id", "name", "enabled"]

def search(self, queryset, name, value): # pylint: disable=unused-argument
"""Free-text search method implementation."""
if not value.strip():
return queryset
return queryset.filter(Q(name__icontains=value) | Q(description__icontains=value)).distinct()


class PeerEndpointFilterSet(RoleModelFilterSetMixin, BaseFilterSet):
"""Filtering of PeerEndpoint records."""

q = django_filters.CharFilter(
method="search",
label="Search",
q = SearchFilter(
filter_predicates={
"routing_instance__device__name": "iexact",
"description": "icontains",
},
)

device = django_filters.ModelMultipleChoiceFilter(
Expand Down Expand Up @@ -215,14 +195,6 @@ class Meta:
model = models.PeerEndpoint
fields = ["id", "enabled"]

def search(self, queryset, name, value): # pylint: disable=unused-argument
"""Free-text search method implementation."""
if not value.strip():
return queryset
return queryset.filter(
Q(routing_instance__device__name__iexact=value) | Q(description__icontains=value)
).distinct()


class PeeringFilterSet(
BaseFilterSet,
Expand All @@ -235,6 +207,12 @@ class PeeringFilterSet(
# TODO(mzb): Add in-memory filtering for Provider, ASN, IP Address, ...
# this requires to consider inheritance methods.

q = SearchFilter(
filter_predicates={
"endpoints__routing_instance__device__name": "icontains",
},
)

device = django_filters.ModelMultipleChoiceFilter(
field_name="endpoints__routing_instance__device__name",
queryset=Device.objects.all(),
Expand Down Expand Up @@ -271,6 +249,12 @@ class Meta:
class AddressFamilyFilterSet(BaseFilterSet, CreatedUpdatedModelFilterSetMixin, CustomFieldModelFilterSetMixin):
"""Filtering of AddressFamily records."""

q = SearchFilter(
filter_predicates={
"routing_instance__device__name": "iexact",
},
)

afi_safi = django_filters.MultipleChoiceFilter(choices=choices.AFISAFIChoices)

routing_instance = django_filters.ModelMultipleChoiceFilter(
Expand Down Expand Up @@ -300,9 +284,12 @@ class Meta:
class PeerGroupAddressFamilyFilterSet(BaseFilterSet, CreatedUpdatedModelFilterSetMixin, CustomFieldModelFilterSetMixin):
"""Filtering of PeerGroupAddressFamily records."""

q = django_filters.CharFilter(
method="search",
label="Search",
q = SearchFilter(
filter_predicates={
"afi_safi": "icontains",
"peer_group__name": "icontains",
"peer_group__description": "icontains",
},
)

afi_safi = django_filters.MultipleChoiceFilter(choices=choices.AFISAFIChoices)
Expand All @@ -320,25 +307,18 @@ class Meta:
"peer_group",
]

def search(self, queryset, name, value): # pylint: disable=unused-argument
"""Free-text search method implementation."""
if not value.strip():
return queryset
return queryset.filter(
Q(afi_safi__icontains=value)
| Q(peer_group__name__icontains=value)
| Q(peer_group__description__icontains=value)
).distinct()


class PeerEndpointAddressFamilyFilterSet(
BaseFilterSet, CreatedUpdatedModelFilterSetMixin, CustomFieldModelFilterSetMixin
):
"""Filtering of PeerEndpointAddressFamily records."""

q = django_filters.CharFilter(
method="search",
label="Search",
q = SearchFilter(
filter_predicates={
"afi_safi": "icontains",
"peer_endpoint__routing_instance__device__name": "iexact",
"peer_endpoint__description": "icontains",
},
)

afi_safi = django_filters.MultipleChoiceFilter(choices=choices.AFISAFIChoices)
Expand All @@ -355,13 +335,3 @@ class Meta:
"afi_safi",
"peer_endpoint",
]

def search(self, queryset, name, value): # pylint: disable=unused-argument
"""Free-text search method implementation."""
if not value.strip():
return queryset
return queryset.filter(
Q(afi_safi__icontains=value)
| Q(peer_endpoint__routing_instance__device__name__iexact=value)
| Q(peer_endpoint__description__icontains=value)
).distinct()
43 changes: 31 additions & 12 deletions nautobot_bgp_models/tests/test_filters.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
"""Unit test automation for FilterSet classes in nautobot_bgp_models."""

from django.contrib.contenttypes.models import ContentType
from django.test import TestCase

# from nautobot.circuits.models import Provider
from nautobot.core.testing import FilterTestCases
from nautobot.dcim.choices import InterfaceTypeChoices
from nautobot.dcim.models import Device, DeviceType, Interface, Location, LocationType, Manufacturer
from nautobot.extras.models import Role, Status
Expand All @@ -12,7 +12,7 @@
from nautobot_bgp_models import choices, filters, models


class AutonomousSystemTestCase(TestCase):
class AutonomousSystemTestCase(FilterTestCases.BaseFilterTestCase):
"""Test filtering of AutonomousSystem records."""

queryset = models.AutonomousSystem.objects.all()
Expand Down Expand Up @@ -55,8 +55,13 @@ def test_status(self):
params = {"status": [self.status_primary_asn.name, self.status_remote_asn.name]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)

def test_search(self):
"""Test filtering by Q search value."""
self.assertEqual(self.filterset({"q": "420"}, self.queryset).qs.count(), 3)
self.assertEqual(self.filterset({"q": "another"}, self.queryset).qs.count(), 1)


class AutonomousSystemRangeTestCase(TestCase):
class AutonomousSystemRangeTestCase(FilterTestCases.BaseFilterTestCase):
"""Test filtering of AutonomousSystemRange records."""

queryset = models.AutonomousSystemRange.objects.all()
Expand Down Expand Up @@ -94,8 +99,12 @@ def test_min_max(self):
params = {"asn_max": [3000]}
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 1)

def test_search(self):
"""Test filtering by Q search value."""
self.assertEqual(self.filterset({"q": "DC"}, self.queryset).qs.count(), 2)


class PeerGroupTestCase(TestCase):
class PeerGroupTestCase(FilterTestCases.BaseFilterTestCase):
"""Test filtering of PeerGroup records."""

queryset = models.PeerGroup.objects.all()
Expand Down Expand Up @@ -219,7 +228,7 @@ def test_routing_instance(self):
)


class PeerEndpointTestCase(TestCase):
class PeerEndpointTestCase(FilterTestCases.BaseFilterTestCase):
"""Test filtering of PeerEndpoint records."""

queryset = models.PeerEndpoint.objects.all()
Expand Down Expand Up @@ -309,7 +318,7 @@ def setUpTestData(cls): # pylint: disable=too-many-locals
def test_search(self):
"""Test text search."""
self.assertEqual(self.filterset({"q": "Device 1"}, self.queryset).qs.count(), 2)
self.assertEqual(self.filterset({"q": "device 1"}, self.queryset).qs.count(), 2)
self.assertEqual(self.filterset({"q": "dev"}, self.queryset).qs.count(), 0)

def test_id(self):
"""Test filtering by ID (primary key)."""
Expand Down Expand Up @@ -342,7 +351,7 @@ def test_device_id(self):
self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)


class PeeringTestCase(TestCase):
class PeeringTestCase(FilterTestCases.BaseFilterTestCase):
"""Test filtering of Peering records."""

queryset = models.Peering.objects.all()
Expand Down Expand Up @@ -656,8 +665,13 @@ def test_peer_endpoint_role(self):
# params = {"address": ["10.1.1.3", "10.1.1.5"]}
# self.assertEqual(self.filterset(params, self.queryset).qs.count(), 2)

def test_search(self):
"""Test filtering by Q search value."""
self.assertEqual(self.filterset({"q": "device1"}, self.queryset).qs.count(), 3)
self.assertEqual(self.filterset({"q": "device2"}, self.queryset).qs.count(), 2)


class AddressFamilyTestCase(TestCase):
class AddressFamilyTestCase(FilterTestCases.BaseFilterTestCase):
"""Test filtering of AddressFamily records."""

queryset = models.AddressFamily.objects.all()
Expand Down Expand Up @@ -742,8 +756,12 @@ def test_afi_safi(self):
def test_device(self):
pass

def test_search(self):
"""Test filtering by Q search value."""
self.assertEqual(self.filterset({"q": "Device 1"}, self.queryset).qs.count(), 3)


class PeerGroupAddressFamilyTestCase(TestCase):
class PeerGroupAddressFamilyTestCase(FilterTestCases.BaseFilterTestCase):
"""Test filtering of PeerGroupAddressFamily records."""

queryset = models.PeerGroupAddressFamily.objects.all()
Expand Down Expand Up @@ -833,7 +851,7 @@ def test_peer_endpoint(self):
self.assertEqual(self.filterset({"peer_group": [self.pg1.pk]}, self.queryset).qs.count(), 2)


class PeerEndpointAddressFamilyTestCase(TestCase):
class PeerEndpointAddressFamilyTestCase(FilterTestCases.BaseFilterTestCase):
"""Test filtering of PeerEndpointAddressFamily records."""

queryset = models.PeerEndpointAddressFamily.objects.all()
Expand Down Expand Up @@ -951,8 +969,9 @@ def setUpTestData(cls):

def test_search(self):
"""Test text search."""
self.assertEqual(self.filterset({"q": "ipv4_unicast"}, self.queryset).qs.count(), 3)
self.assertEqual(self.filterset({"q": self.pe1.description}, self.queryset).qs.count(), 2)
self.assertEqual(self.filterset({"q": "ipv4_uni"}, self.queryset).qs.count(), 3)
self.assertEqual(self.filterset({"q": "endpoint"}, self.queryset).qs.count(), 2)
self.assertEqual(self.filterset({"q": "Device 1"}, self.queryset).qs.count(), 3)

def test_id(self):
"""Test filtering by ID (primary key)."""
Expand Down

0 comments on commit e4ba1f1

Please sign in to comment.