mirror of
https://github.com/netbox-community/netbox.git
synced 2025-07-24 17:38:37 -06:00
Ditch CustomFieldFilter
This commit is contained in:
parent
6377d475fc
commit
7c60089692
@ -1,47 +1,11 @@
|
|||||||
import django_filters
|
import django_filters
|
||||||
from django.forms import DateField, IntegerField, NullBooleanField
|
|
||||||
|
|
||||||
from .models import Tag
|
from .models import Tag
|
||||||
from .choices import *
|
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'CustomFieldFilter',
|
|
||||||
'TagFilter',
|
'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):
|
class TagFilter(django_filters.ModelMultipleChoiceFilter):
|
||||||
"""
|
"""
|
||||||
|
@ -26,13 +26,6 @@ __all__ = (
|
|||||||
'WebhookFilterSet',
|
'WebhookFilterSet',
|
||||||
)
|
)
|
||||||
|
|
||||||
EXACT_FILTER_TYPES = (
|
|
||||||
CustomFieldTypeChoices.TYPE_BOOLEAN,
|
|
||||||
CustomFieldTypeChoices.TYPE_DATE,
|
|
||||||
CustomFieldTypeChoices.TYPE_INTEGER,
|
|
||||||
CustomFieldTypeChoices.TYPE_SELECT,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class WebhookFilterSet(BaseFilterSet):
|
class WebhookFilterSet(BaseFilterSet):
|
||||||
content_types = ContentTypeFilter()
|
content_types = ContentTypeFilter()
|
||||||
|
@ -8,6 +8,7 @@ from django.core.validators import RegexValidator, ValidationError
|
|||||||
from django.db import models
|
from django.db import models
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
from django.utils.safestring import mark_safe
|
from django.utils.safestring import mark_safe
|
||||||
|
from django_filters import filters
|
||||||
|
|
||||||
from extras.choices import *
|
from extras.choices import *
|
||||||
from extras.utils import FeatureQuery, extras_features
|
from extras.utils import FeatureQuery, extras_features
|
||||||
@ -308,6 +309,53 @@ class CustomField(ChangeLoggedModel):
|
|||||||
|
|
||||||
return field
|
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):
|
def validate(self, value):
|
||||||
"""
|
"""
|
||||||
Validate a value according to the field's type validation rules.
|
Validate a value according to the field's type validation rules.
|
||||||
|
@ -7,7 +7,7 @@ from django_filters.utils import get_model_field, resolve_field
|
|||||||
|
|
||||||
from dcim.forms import MACAddressField
|
from dcim.forms import MACAddressField
|
||||||
from extras.choices import CustomFieldFilterLogicChoices
|
from extras.choices import CustomFieldFilterLogicChoices
|
||||||
from extras.filters import CustomFieldFilter, TagFilter
|
from extras.filters import TagFilter
|
||||||
from extras.models import CustomField
|
from extras.models import CustomField
|
||||||
from utilities.constants import (
|
from utilities.constants import (
|
||||||
FILTER_CHAR_BASED_LOOKUP_MAP, FILTER_NEGATION_LOOKUP_MAP, FILTER_TREENODE_NEGATION_LOOKUP_MAP,
|
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
|
from utilities import filters
|
||||||
|
|
||||||
|
|
||||||
__all__ = (
|
__all__ = (
|
||||||
'BaseFilterSet',
|
'BaseFilterSet',
|
||||||
'ChangeLoggedModelFilterSet',
|
'ChangeLoggedModelFilterSet',
|
||||||
@ -222,8 +221,10 @@ class PrimaryModelFilterSet(ChangeLoggedModelFilterSet):
|
|||||||
)
|
)
|
||||||
|
|
||||||
custom_field_filters = {}
|
custom_field_filters = {}
|
||||||
for cf in custom_fields:
|
for custom_field in custom_fields:
|
||||||
custom_field_filters[f'cf_{cf.name}'] = CustomFieldFilter(field_name=cf.name, custom_field=cf)
|
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)
|
self.filters.update(custom_field_filters)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user