Implemented dynamic filters for custom fields

This commit is contained in:
Jeremy Stretch 2016-08-23 11:18:00 -04:00
parent 3b36a35b9a
commit 28b9dda55d
5 changed files with 47 additions and 12 deletions

View File

@ -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',

View File

@ -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
netbox/extras/filters.py Normal file
View File

@ -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)

View File

@ -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',

View File

@ -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',