Просмотр исходного кода

Extract base NestedGroupModelFilterSet with base search behavior

This can easily be extended (as in the case of LocationFilterSet) by
calling super() and ORing a filter to the queryset that is returned.
See: https://docs.djangoproject.com/en/5.1/ref/models/querysets/#or
Jason Novinger 11 месяцев назад
Родитель
Сommit
06a206ee33
4 измененных файлов с 33 добавлено и 68 удалено
  1. 12 33
      netbox/dcim/filtersets.py
  2. 16 0
      netbox/netbox/filtersets.py
  3. 3 23
      netbox/tenancy/filtersets.py
  4. 2 12
      netbox/wireless/filtersets.py

+ 12 - 33
netbox/dcim/filtersets.py

@@ -11,7 +11,8 @@ from ipam.filtersets import PrimaryIPFilterSet
 from ipam.models import ASN, IPAddress, VLANTranslationPolicy, VRF
 from netbox.choices import ColorChoices
 from netbox.filtersets import (
-    BaseFilterSet, ChangeLoggedModelFilterSet, OrganizationalModelFilterSet, NetBoxModelFilterSet,
+    BaseFilterSet, ChangeLoggedModelFilterSet, NestedGroupModelFilterSet, NetBoxModelFilterSet,
+    OrganizationalModelFilterSet,
 )
 from tenancy.filtersets import TenancyFilterSet, ContactModelFilterSet
 from tenancy.models import *
@@ -81,7 +82,7 @@ __all__ = (
 )
 
 
-class RegionFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
+class RegionFilterSet(NestedGroupModelFilterSet, ContactModelFilterSet):
     parent_id = django_filters.ModelMultipleChoiceFilter(
         queryset=Region.objects.all(),
         label=_('Parent region (ID)'),
@@ -110,18 +111,8 @@ class RegionFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
         model = Region
         fields = ('id', 'name', 'slug', 'description')
 
-    def search(self, queryset, name, value):
-        if not value.strip():
-            return queryset
-        return queryset.filter(
-            Q(name__icontains=value) |
-            Q(slug__icontains=value) |
-            Q(description__icontains=value) |
-            Q(comments__icontains=value)
-        ).distinct()
-
 
-class SiteGroupFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
+class SiteGroupFilterSet(NestedGroupModelFilterSet, ContactModelFilterSet):
     parent_id = django_filters.ModelMultipleChoiceFilter(
         queryset=SiteGroup.objects.all(),
         label=_('Parent site group (ID)'),
@@ -150,16 +141,6 @@ class SiteGroupFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
         model = SiteGroup
         fields = ('id', 'name', 'slug', 'description')
 
-    def search(self, queryset, name, value):
-        if not value.strip():
-            return queryset
-        return queryset.filter(
-            Q(name__icontains=value) |
-            Q(slug__icontains=value) |
-            Q(description__icontains=value) |
-            Q(comments__icontains=value)
-        ).distinct()
-
 
 class SiteFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
     status = django_filters.MultipleChoiceFilter(
@@ -225,7 +206,7 @@ class SiteFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSe
         return queryset.filter(qs_filter).distinct()
 
 
-class LocationFilterSet(TenancyFilterSet, ContactModelFilterSet, OrganizationalModelFilterSet):
+class LocationFilterSet(TenancyFilterSet, ContactModelFilterSet, NestedGroupModelFilterSet):
     region_id = TreeNodeMultipleChoiceFilter(
         queryset=Region.objects.all(),
         field_name='site__region',
@@ -295,15 +276,13 @@ class LocationFilterSet(TenancyFilterSet, ContactModelFilterSet, OrganizationalM
         fields = ('id', 'name', 'slug', 'facility', 'description')
 
     def search(self, queryset, name, value):
-        if not value.strip():
-            return queryset
-        return queryset.filter(
-            Q(name__icontains=value) |
-            Q(slug__icontains=value) |
-            Q(facility__icontains=value) |
-            Q(description__icontains=value) |
-            Q(comments__icontains=value)
-        )
+        # extended in order to include querying on Location.facility
+        queryset = super().search(queryset, name, value)
+
+        if value.strip():
+            queryset = queryset | queryset.model.objects.filter(facility__icontains=value)
+
+        return queryset
 
 
 class RackRoleFilterSet(OrganizationalModelFilterSet):

+ 16 - 0
netbox/netbox/filtersets.py

@@ -329,3 +329,19 @@ class OrganizationalModelFilterSet(NetBoxModelFilterSet):
             models.Q(slug__icontains=value) |
             models.Q(description__icontains=value)
         )
+
+
+class NestedGroupModelFilterSet(NetBoxModelFilterSet):
+    """
+    A base FilterSet for models that inherit from NestedGroupModel
+    """
+    def search(self, queryset, name, value):
+        if value.strip():
+            queryset = queryset.filter(
+                models.Q(name__icontains=value) |
+                models.Q(slug__icontains=value) |
+                models.Q(description__icontains=value) |
+                models.Q(comments__icontains=value)
+            )
+
+        return queryset

+ 3 - 23
netbox/tenancy/filtersets.py

@@ -2,7 +2,7 @@ import django_filters
 from django.db.models import Q
 from django.utils.translation import gettext as _
 
-from netbox.filtersets import NetBoxModelFilterSet, OrganizationalModelFilterSet
+from netbox.filtersets import NestedGroupModelFilterSet, NetBoxModelFilterSet, OrganizationalModelFilterSet
 from utilities.filters import ContentTypeFilter, TreeNodeMultipleChoiceFilter
 from .models import *
 
@@ -22,7 +22,7 @@ __all__ = (
 # Contacts
 #
 
-class ContactGroupFilterSet(OrganizationalModelFilterSet):
+class ContactGroupFilterSet(NestedGroupModelFilterSet):
     parent_id = django_filters.ModelMultipleChoiceFilter(
         queryset=ContactGroup.objects.all(),
         label=_('Parent contact group (ID)'),
@@ -51,16 +51,6 @@ class ContactGroupFilterSet(OrganizationalModelFilterSet):
         model = ContactGroup
         fields = ('id', 'name', 'slug', 'description')
 
-    def search(self, queryset, name, value):
-        if not value.strip():
-            return queryset
-        return queryset.filter(
-            Q(name__icontains=value) |
-            Q(slug__icontains=value) |
-            Q(description__icontains=value) |
-            Q(comments__icontains=value)
-        )
-
 
 class ContactRoleFilterSet(OrganizationalModelFilterSet):
 
@@ -173,7 +163,7 @@ class ContactModelFilterSet(django_filters.FilterSet):
 # Tenancy
 #
 
-class TenantGroupFilterSet(OrganizationalModelFilterSet):
+class TenantGroupFilterSet(NestedGroupModelFilterSet):
     parent_id = django_filters.ModelMultipleChoiceFilter(
         queryset=TenantGroup.objects.all(),
         label=_('Parent tenant group (ID)'),
@@ -202,16 +192,6 @@ class TenantGroupFilterSet(OrganizationalModelFilterSet):
         model = TenantGroup
         fields = ('id', 'name', 'slug', 'description')
 
-    def search(self, queryset, name, value):
-        if not value.strip():
-            return queryset
-        return queryset.filter(
-            Q(name__icontains=value) |
-            Q(slug__icontains=value) |
-            Q(description__icontains=value) |
-            Q(comments__icontains=value)
-        )
-
 
 class TenantFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
     group_id = TreeNodeMultipleChoiceFilter(

+ 2 - 12
netbox/wireless/filtersets.py

@@ -5,7 +5,7 @@ from dcim.choices import LinkStatusChoices
 from dcim.base_filtersets import ScopedFilterSet
 from dcim.models import Interface
 from ipam.models import VLAN
-from netbox.filtersets import OrganizationalModelFilterSet, NetBoxModelFilterSet
+from netbox.filtersets import NestedGroupModelFilterSet, NetBoxModelFilterSet
 from tenancy.filtersets import TenancyFilterSet
 from utilities.filters import TreeNodeMultipleChoiceFilter
 from .choices import *
@@ -18,7 +18,7 @@ __all__ = (
 )
 
 
-class WirelessLANGroupFilterSet(OrganizationalModelFilterSet):
+class WirelessLANGroupFilterSet(NestedGroupModelFilterSet):
     parent_id = django_filters.ModelMultipleChoiceFilter(
         queryset=WirelessLANGroup.objects.all()
     )
@@ -43,16 +43,6 @@ class WirelessLANGroupFilterSet(OrganizationalModelFilterSet):
         model = WirelessLANGroup
         fields = ('id', 'name', 'slug', 'description')
 
-    def search(self, queryset, name, value):
-        if not value.strip():
-            return queryset
-        return queryset.filter(
-            Q(name__icontains=value) |
-            Q(slug__icontains=value) |
-            Q(description__icontains=value) |
-            Q(comments__icontains=value)
-        )
-
 
 class WirelessLANFilterSet(NetBoxModelFilterSet, ScopedFilterSet, TenancyFilterSet):
     group_id = TreeNodeMultipleChoiceFilter(