Parcourir la source

Implemented dynamic filters for custom fields

Jeremy Stretch il y a 8 ans
Parent
commit
28b9dda55d

+ 3 - 2
netbox/circuits/filters.py

@@ -3,11 +3,12 @@ import django_filters
 from django.db.models import Q
 
 from dcim.models import Site
+from extras.filters import CustomFieldFilterSet
 from tenancy.models import Tenant
 from .models import Provider, Circuit, CircuitType
 
 
-class ProviderFilter(django_filters.FilterSet):
+class ProviderFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
         action='search',
         label='Search',
@@ -36,7 +37,7 @@ class ProviderFilter(django_filters.FilterSet):
         )
 
 
-class CircuitFilter(django_filters.FilterSet):
+class CircuitFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
         action='search',
         label='Search',

+ 5 - 4
netbox/dcim/filters.py

@@ -2,14 +2,15 @@ import django_filters
 
 from django.db.models import Q
 
+from extras.filters import CustomFieldFilterSet
+from tenancy.models import Tenant
 from .models import (
     ConsolePort, ConsoleServerPort, Device, DeviceRole, DeviceType, Interface, InterfaceConnection, Manufacturer,
     Platform, PowerOutlet, PowerPort, Rack, RackGroup, RackRole, Site,
 )
-from tenancy.models import Tenant
 
 
-class SiteFilter(django_filters.FilterSet):
+class SiteFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
         action='search',
         label='Search',
@@ -58,7 +59,7 @@ class RackGroupFilter(django_filters.FilterSet):
         fields = ['site_id', 'site']
 
 
-class RackFilter(django_filters.FilterSet):
+class RackFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
         action='search',
         label='Search',
@@ -139,7 +140,7 @@ class DeviceTypeFilter(django_filters.FilterSet):
                   'is_network_device']
 
 
-class DeviceFilter(django_filters.FilterSet):
+class DeviceFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
         action='search',
         label='Search',

+ 31 - 0
netbox/extras/filters.py

@@ -0,0 +1,31 @@
+import django_filters
+
+from django.contrib.contenttypes.models import ContentType
+
+from .models import CustomField
+
+
+class CustomFieldFilter(django_filters.Filter):
+    """
+    Filter objects by the presence of a CustomFieldValue. The filter's name is used as the CustomField name.
+    """
+
+    def filter(self, queryset, value):
+        return queryset.filter(
+            custom_field_values__field__name=self.name,
+            custom_field_values__serialized_value=value,
+        )
+
+
+class CustomFieldFilterSet(django_filters.FilterSet):
+    """
+    Dynamically add a Filter for each CustomField applicable to the parent model.
+    """
+
+    def __init__(self, *args, **kwargs):
+        super(CustomFieldFilterSet, self).__init__(*args, **kwargs)
+
+        obj_type = ContentType.objects.get_for_model(self._meta.model)
+        custom_fields = CustomField.objects.filter(obj_type=obj_type)
+        for cf in custom_fields:
+            self.filters['cf_{}'.format(cf.name)] = CustomFieldFilter(name=cf.name)

+ 6 - 5
netbox/ipam/filters.py

@@ -5,12 +5,13 @@ from netaddr.core import AddrFormatError
 from django.db.models import Q
 
 from dcim.models import Site, Device, Interface
+from extras.filters import CustomFieldFilterSet
 from tenancy.models import Tenant
 
 from .models import RIR, Aggregate, VRF, Prefix, IPAddress, VLAN, VLANGroup, Role
 
 
-class VRFFilter(django_filters.FilterSet):
+class VRFFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
         action='search',
         label='Search',
@@ -44,7 +45,7 @@ class VRFFilter(django_filters.FilterSet):
         fields = ['name', 'rd']
 
 
-class AggregateFilter(django_filters.FilterSet):
+class AggregateFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
         action='search',
         label='Search',
@@ -75,7 +76,7 @@ class AggregateFilter(django_filters.FilterSet):
         return queryset.filter(qs_filter)
 
 
-class PrefixFilter(django_filters.FilterSet):
+class PrefixFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
         action='search',
         label='Search',
@@ -186,7 +187,7 @@ class PrefixFilter(django_filters.FilterSet):
         )
 
 
-class IPAddressFilter(django_filters.FilterSet):
+class IPAddressFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
         action='search',
         label='Search',
@@ -300,7 +301,7 @@ class VLANGroupFilter(django_filters.FilterSet):
         fields = ['site_id', 'site']
 
 
-class VLANFilter(django_filters.FilterSet):
+class VLANFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
         action='search',
         label='Search',

+ 2 - 1
netbox/tenancy/filters.py

@@ -2,10 +2,11 @@ import django_filters
 
 from django.db.models import Q
 
+from extras.filters import CustomFieldFilterSet
 from .models import Tenant, TenantGroup
 
 
-class TenantFilter(django_filters.FilterSet):
+class TenantFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
         action='search',
         label='Search',