Ditch CustomFieldFilter

This commit is contained in:
jeremystretch 2021-10-28 15:31:50 -04:00
parent 6377d475fc
commit 7c60089692
4 changed files with 53 additions and 47 deletions

View File

@ -1,47 +1,11 @@
import django_filters
from django.forms import DateField, IntegerField, NullBooleanField
from .models import Tag
from .choices import *
__all__ = (
'CustomFieldFilter',
'TagFilter',
)
EXACT_FILTER_TYPES = (
CustomFieldTypeChoices.TYPE_BOOLEAN,
CustomFieldTypeChoices.TYPE_DATE,
CustomFieldTypeChoices.TYPE_INTEGER,
CustomFieldTypeChoices.TYPE_SELECT,
CustomFieldTypeChoices.TYPE_MULTISELECT,
)
class CustomFieldFilter(django_filters.Filter):
"""
Filter objects by the presence of a CustomFieldValue. The filter's name is used as the CustomField name.
"""
def __init__(self, custom_field, *args, **kwargs):
self.custom_field = custom_field
if custom_field.type == CustomFieldTypeChoices.TYPE_INTEGER:
self.field_class = IntegerField
elif custom_field.type == CustomFieldTypeChoices.TYPE_BOOLEAN:
self.field_class = NullBooleanField
elif custom_field.type == CustomFieldTypeChoices.TYPE_DATE:
self.field_class = DateField
super().__init__(*args, **kwargs)
self.field_name = f'custom_field_data__{self.field_name}'
if custom_field.type == CustomFieldTypeChoices.TYPE_MULTISELECT:
self.lookup_expr = 'has_key'
elif custom_field.type not in EXACT_FILTER_TYPES:
if custom_field.filter_logic == CustomFieldFilterLogicChoices.FILTER_LOOSE:
self.lookup_expr = 'icontains'
class TagFilter(django_filters.ModelMultipleChoiceFilter):
"""

View File

@ -26,13 +26,6 @@ __all__ = (
'WebhookFilterSet',
)
EXACT_FILTER_TYPES = (
CustomFieldTypeChoices.TYPE_BOOLEAN,
CustomFieldTypeChoices.TYPE_DATE,
CustomFieldTypeChoices.TYPE_INTEGER,
CustomFieldTypeChoices.TYPE_SELECT,
)
class WebhookFilterSet(BaseFilterSet):
content_types = ContentTypeFilter()

View File

@ -8,6 +8,7 @@ from django.core.validators import RegexValidator, ValidationError
from django.db import models
from django.urls import reverse
from django.utils.safestring import mark_safe
from django_filters import filters
from extras.choices import *
from extras.utils import FeatureQuery, extras_features
@ -308,6 +309,53 @@ class CustomField(ChangeLoggedModel):
return field
def to_filter(self):
"""
Return a django_filters Filter instance suitable for this field type.
"""
kwargs = {
'field_name': f'custom_field_data__{self.name}'
}
# Text/URL
if self.type in (
CustomFieldTypeChoices.TYPE_TEXT,
CustomFieldTypeChoices.TYPE_LONGTEXT,
CustomFieldTypeChoices.TYPE_URL,
):
filter_class = filters.CharFilter
if self.filter_logic == CustomFieldFilterLogicChoices.FILTER_LOOSE:
kwargs['lookup_expr'] = 'icontains'
# Integer
elif self.type == CustomFieldTypeChoices.TYPE_INTEGER:
# TODO: Remove dirty hack to change lookup type from Decimal
filter_class = filters.NumberFilter
filter_class.field_class = forms.IntegerField
# Boolean
elif self.type == CustomFieldTypeChoices.TYPE_BOOLEAN:
filter_class = filters.BooleanFilter
# Date
elif self.type == CustomFieldTypeChoices.TYPE_DATE:
filter_class = filters.DateFilter
# Select
elif self.type == CustomFieldTypeChoices.TYPE_SELECT:
filter_class = filters.CharFilter
# Multiselect
elif self.type == CustomFieldTypeChoices.TYPE_MULTISELECT:
filter_class = filters.CharFilter
kwargs['lookup_expr'] = 'has_key'
# Unsupported custom field type
else:
return None
return filter_class(**kwargs)
def validate(self, value):
"""
Validate a value according to the field's type validation rules.

View File

@ -7,7 +7,7 @@ from django_filters.utils import get_model_field, resolve_field
from dcim.forms import MACAddressField
from extras.choices import CustomFieldFilterLogicChoices
from extras.filters import CustomFieldFilter, TagFilter
from extras.filters import TagFilter
from extras.models import CustomField
from utilities.constants import (
FILTER_CHAR_BASED_LOOKUP_MAP, FILTER_NEGATION_LOOKUP_MAP, FILTER_TREENODE_NEGATION_LOOKUP_MAP,
@ -15,7 +15,6 @@ from utilities.constants import (
)
from utilities import filters
__all__ = (
'BaseFilterSet',
'ChangeLoggedModelFilterSet',
@ -222,8 +221,10 @@ class PrimaryModelFilterSet(ChangeLoggedModelFilterSet):
)
custom_field_filters = {}
for cf in custom_fields:
custom_field_filters[f'cf_{cf.name}'] = CustomFieldFilter(field_name=cf.name, custom_field=cf)
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
self.filters.update(custom_field_filters)