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 django.db.models import Q
 
 
 from dcim.models import Site
 from dcim.models import Site
+from extras.filters import CustomFieldFilterSet
 from tenancy.models import Tenant
 from tenancy.models import Tenant
 from .models import Provider, Circuit, CircuitType
 from .models import Provider, Circuit, CircuitType
 
 
 
 
-class ProviderFilter(django_filters.FilterSet):
+class ProviderFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
     q = django_filters.MethodFilter(
         action='search',
         action='search',
         label='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(
     q = django_filters.MethodFilter(
         action='search',
         action='search',
         label='Search',
         label='Search',

+ 5 - 4
netbox/dcim/filters.py

@@ -2,14 +2,15 @@ import django_filters
 
 
 from django.db.models import Q
 from django.db.models import Q
 
 
+from extras.filters import CustomFieldFilterSet
+from tenancy.models import Tenant
 from .models import (
 from .models import (
     ConsolePort, ConsoleServerPort, Device, DeviceRole, DeviceType, Interface, InterfaceConnection, Manufacturer,
     ConsolePort, ConsoleServerPort, Device, DeviceRole, DeviceType, Interface, InterfaceConnection, Manufacturer,
     Platform, PowerOutlet, PowerPort, Rack, RackGroup, RackRole, Site,
     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(
     q = django_filters.MethodFilter(
         action='search',
         action='search',
         label='Search',
         label='Search',
@@ -58,7 +59,7 @@ class RackGroupFilter(django_filters.FilterSet):
         fields = ['site_id', 'site']
         fields = ['site_id', 'site']
 
 
 
 
-class RackFilter(django_filters.FilterSet):
+class RackFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
     q = django_filters.MethodFilter(
         action='search',
         action='search',
         label='Search',
         label='Search',
@@ -139,7 +140,7 @@ class DeviceTypeFilter(django_filters.FilterSet):
                   'is_network_device']
                   'is_network_device']
 
 
 
 
-class DeviceFilter(django_filters.FilterSet):
+class DeviceFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
     q = django_filters.MethodFilter(
         action='search',
         action='search',
         label='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 django.db.models import Q
 
 
 from dcim.models import Site, Device, Interface
 from dcim.models import Site, Device, Interface
+from extras.filters import CustomFieldFilterSet
 from tenancy.models import Tenant
 from tenancy.models import Tenant
 
 
 from .models import RIR, Aggregate, VRF, Prefix, IPAddress, VLAN, VLANGroup, Role
 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(
     q = django_filters.MethodFilter(
         action='search',
         action='search',
         label='Search',
         label='Search',
@@ -44,7 +45,7 @@ class VRFFilter(django_filters.FilterSet):
         fields = ['name', 'rd']
         fields = ['name', 'rd']
 
 
 
 
-class AggregateFilter(django_filters.FilterSet):
+class AggregateFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
     q = django_filters.MethodFilter(
         action='search',
         action='search',
         label='Search',
         label='Search',
@@ -75,7 +76,7 @@ class AggregateFilter(django_filters.FilterSet):
         return queryset.filter(qs_filter)
         return queryset.filter(qs_filter)
 
 
 
 
-class PrefixFilter(django_filters.FilterSet):
+class PrefixFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
     q = django_filters.MethodFilter(
         action='search',
         action='search',
         label='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(
     q = django_filters.MethodFilter(
         action='search',
         action='search',
         label='Search',
         label='Search',
@@ -300,7 +301,7 @@ class VLANGroupFilter(django_filters.FilterSet):
         fields = ['site_id', 'site']
         fields = ['site_id', 'site']
 
 
 
 
-class VLANFilter(django_filters.FilterSet):
+class VLANFilter(CustomFieldFilterSet, django_filters.FilterSet):
     q = django_filters.MethodFilter(
     q = django_filters.MethodFilter(
         action='search',
         action='search',
         label='Search',
         label='Search',

+ 2 - 1
netbox/tenancy/filters.py

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