From 2e0f15b35fbe72ab1f9b890dd7740e6e94d81550 Mon Sep 17 00:00:00 2001 From: jeremystretch Date: Thu, 28 Oct 2021 16:09:36 -0400 Subject: [PATCH] Automatically add additional lookup filters for custom fields --- netbox/extras/models/customfields.py | 11 +++++++++-- netbox/netbox/filtersets.py | 16 +++++++++++++--- 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/netbox/extras/models/customfields.py b/netbox/extras/models/customfields.py index a889762f9..5f60c6fea 100644 --- a/netbox/extras/models/customfields.py +++ b/netbox/extras/models/customfields.py @@ -309,13 +309,17 @@ class CustomField(ChangeLoggedModel): return field - def to_filter(self): + def to_filter(self, lookup_expr=None): """ Return a django_filters Filter instance suitable for this field type. + + :param lookup_expr: Custom lookup expression (optional) """ kwargs = { 'field_name': f'custom_field_data__{self.name}' } + if lookup_expr is not None: + kwargs['lookup_expr'] = lookup_expr # Text/URL if self.type in ( @@ -354,7 +358,10 @@ class CustomField(ChangeLoggedModel): else: return None - return filter_class(**kwargs) + filter_instance = filter_class(**kwargs) + filter_instance.custom_field = self + + return filter_instance def validate(self, value): """ diff --git a/netbox/netbox/filtersets.py b/netbox/netbox/filtersets.py index ea0b9eda0..fff08693e 100644 --- a/netbox/netbox/filtersets.py +++ b/netbox/netbox/filtersets.py @@ -84,6 +84,7 @@ class BaseFilterSet(django_filters.FilterSet): def _get_filter_lookup_dict(existing_filter): # Choose the lookup expression map based on the filter type if isinstance(existing_filter, ( + django_filters.NumberFilter, filters.MultiValueDateFilter, filters.MultiValueDateTimeFilter, filters.MultiValueNumberFilter, @@ -151,6 +152,10 @@ class BaseFilterSet(django_filters.FilterSet): distinct=existing_filter.distinct, **existing_filter.extra ) + elif hasattr(existing_filter, 'custom_field'): + # Filter is for a custom field + custom_field = existing_filter.custom_field + new_filter = custom_field.to_filter(lookup_expr=lookup_expr) else: # The filter field is listed in Meta.fields so we can safely rely on default behaviour # Will raise FieldLookupError if the lookup is invalid @@ -222,9 +227,14 @@ class PrimaryModelFilterSet(ChangeLoggedModelFilterSet): custom_field_filters = {} for custom_field in custom_fields: - cf_filter = custom_field.to_filter() - if cf_filter: - custom_field_filters[f'cf_{custom_field.name}'] = cf_filter + filter_name = f'cf_{custom_field.name}' + filter_instance = custom_field.to_filter() + if filter_instance: + custom_field_filters[filter_name] = filter_instance + + # Add relevant additional lookups + additional_lookups = self.get_additional_lookups(filter_name, filter_instance) + custom_field_filters.update(additional_lookups) self.filters.update(custom_field_filters)