diff --git a/netbox/extras/choices.py b/netbox/extras/choices.py index ec721c552..1ae508c4a 100644 --- a/netbox/extras/choices.py +++ b/netbox/extras/choices.py @@ -31,3 +31,22 @@ class CustomFieldTypeChoices(ChoiceSet): TYPE_URL: 500, TYPE_SELECT: 600, } + + +class CustomFieldFilterLogicChoices(ChoiceSet): + + FILTER_DISABLED = 'disabled' + FILTER_LOOSE = 'loose' + FILTER_EXACT = 'exact' + + CHOICES = ( + (FILTER_DISABLED, 'Disabled'), + (FILTER_LOOSE, 'Loose'), + (FILTER_EXACT, 'Exact'), + ) + + LEGACY_MAP = { + FILTER_DISABLED: 0, + FILTER_LOOSE: 1, + FILTER_EXACT: 2, + } diff --git a/netbox/extras/constants.py b/netbox/extras/constants.py index 850167235..4d4e8835e 100644 --- a/netbox/extras/constants.py +++ b/netbox/extras/constants.py @@ -19,16 +19,6 @@ CUSTOMFIELD_MODELS = [ 'virtualization.virtualmachine', ] -# Custom field filter logic choices -CF_FILTER_DISABLED = 0 -CF_FILTER_LOOSE = 1 -CF_FILTER_EXACT = 2 -CF_FILTER_CHOICES = ( - (CF_FILTER_DISABLED, 'Disabled'), - (CF_FILTER_LOOSE, 'Loose'), - (CF_FILTER_EXACT, 'Exact'), -) - # Custom links CUSTOMLINK_MODELS = [ 'circuits.circuit', diff --git a/netbox/extras/filters.py b/netbox/extras/filters.py index a3c488281..9e954eaf1 100644 --- a/netbox/extras/filters.py +++ b/netbox/extras/filters.py @@ -43,7 +43,8 @@ class CustomFieldFilter(django_filters.Filter): return queryset.none() # Apply the assigned filter logic (exact or loose) - if self.cf_type == CustomFieldTypeChoices.TYPE_BOOLEAN or self.filter_logic == CF_FILTER_EXACT: + if (self.cf_type == CustomFieldTypeChoices.TYPE_BOOLEAN or + self.filter_logic == CustomFieldFilterLogicChoices.FILTER_EXACT): queryset = queryset.filter( custom_field_values__field__name=self.field_name, custom_field_values__serialized_value=value @@ -66,7 +67,11 @@ class CustomFieldFilterSet(django_filters.FilterSet): super().__init__(*args, **kwargs) obj_type = ContentType.objects.get_for_model(self._meta.model) - custom_fields = CustomField.objects.filter(obj_type=obj_type).exclude(filter_logic=CF_FILTER_DISABLED) + custom_fields = CustomField.objects.filter( + obj_type=obj_type + ).exclude( + filter_logic=CustomFieldFilterLogicChoices.FILTER_DISABLED + ) for cf in custom_fields: self.filters['cf_{}'.format(cf.name)] = CustomFieldFilter(field_name=cf.name, custom_field=cf) diff --git a/netbox/extras/forms.py b/netbox/extras/forms.py index c6dbeaf8d..34583eb0d 100644 --- a/netbox/extras/forms.py +++ b/netbox/extras/forms.py @@ -29,7 +29,7 @@ def get_custom_fields_for_model(content_type, filterable_only=False, bulk_edit=F field_dict = OrderedDict() custom_fields = CustomField.objects.filter(obj_type=content_type) if filterable_only: - custom_fields = custom_fields.exclude(filter_logic=CF_FILTER_DISABLED) + custom_fields = custom_fields.exclude(filter_logic=CustomFieldFilterLogicChoices.FILTER_DISABLED) for cf in custom_fields: field_name = 'cf_{}'.format(str(cf.name)) diff --git a/netbox/extras/migrations/0010_customfield_filter_logic.py b/netbox/extras/migrations/0010_customfield_filter_logic.py index f153c9d11..dcc2d6ad6 100644 --- a/netbox/extras/migrations/0010_customfield_filter_logic.py +++ b/netbox/extras/migrations/0010_customfield_filter_logic.py @@ -2,21 +2,19 @@ # Generated by Django 1.11.9 on 2018-02-21 19:48 from django.db import migrations, models -from extras.constants import CF_FILTER_DISABLED, CF_FILTER_EXACT, CF_FILTER_LOOSE - def is_filterable_to_filter_logic(apps, schema_editor): CustomField = apps.get_model('extras', 'CustomField') - CustomField.objects.filter(is_filterable=False).update(filter_logic=CF_FILTER_DISABLED) - CustomField.objects.filter(is_filterable=True).update(filter_logic=CF_FILTER_LOOSE) + CustomField.objects.filter(is_filterable=False).update(filter_logic=0) + CustomField.objects.filter(is_filterable=True).update(filter_logic=1) # Select fields match on primary key only - CustomField.objects.filter(is_filterable=True, type=600).update(filter_logic=CF_FILTER_EXACT) + CustomField.objects.filter(is_filterable=True, type=600).update(filter_logic=2) def filter_logic_to_is_filterable(apps, schema_editor): CustomField = apps.get_model('extras', 'CustomField') - CustomField.objects.filter(filter_logic=CF_FILTER_DISABLED).update(is_filterable=False) - CustomField.objects.exclude(filter_logic=CF_FILTER_DISABLED).update(is_filterable=True) + CustomField.objects.filter(filter_logic=0).update(is_filterable=False) + CustomField.objects.exclude(filter_logic=0).update(is_filterable=True) class Migration(migrations.Migration): diff --git a/netbox/extras/migrations/0029_3569_customfield_fields.py b/netbox/extras/migrations/0029_3569_customfield_fields.py index 436f1c9e8..7eced66e9 100644 --- a/netbox/extras/migrations/0029_3569_customfield_fields.py +++ b/netbox/extras/migrations/0029_3569_customfield_fields.py @@ -10,6 +10,12 @@ CUSTOMFIELD_TYPE_CHOICES = ( (600, 'select') ) +CUSTOMFIELD_FILTER_LOGIC_CHOICES = ( + (0, 'disabled'), + (1, 'integer'), + (2, 'exact'), +) + def customfield_type_to_slug(apps, schema_editor): CustomField = apps.get_model('extras', 'CustomField') @@ -17,6 +23,12 @@ def customfield_type_to_slug(apps, schema_editor): CustomField.objects.filter(type=str(id)).update(type=slug) +def customfield_filter_logic_to_slug(apps, schema_editor): + CustomField = apps.get_model('extras', 'CustomField') + for id, slug in CUSTOMFIELD_FILTER_LOGIC_CHOICES: + CustomField.objects.filter(filter_logic=str(id)).update(filter_logic=slug) + + class Migration(migrations.Migration): atomic = False @@ -25,6 +37,8 @@ class Migration(migrations.Migration): ] operations = [ + + # CustomField.type migrations.AlterField( model_name='customfield', name='type', @@ -33,4 +47,15 @@ class Migration(migrations.Migration): migrations.RunPython( code=customfield_type_to_slug ), + + # CustomField.filter_logic + migrations.AlterField( + model_name='customfield', + name='filter_logic', + field=models.CharField(default='loose', max_length=50), + ), + migrations.RunPython( + code=customfield_filter_logic_to_slug + ), + ] diff --git a/netbox/extras/models.py b/netbox/extras/models.py index 163258b15..8278cc19a 100644 --- a/netbox/extras/models.py +++ b/netbox/extras/models.py @@ -207,9 +207,10 @@ class CustomField(models.Model): help_text='If true, this field is required when creating new objects ' 'or editing an existing object.' ) - filter_logic = models.PositiveSmallIntegerField( - choices=CF_FILTER_CHOICES, - default=CF_FILTER_LOOSE, + filter_logic = models.CharField( + max_length=50, + choices=CustomFieldFilterLogicChoices, + default=CustomFieldFilterLogicChoices.FILTER_LOOSE, help_text='Loose matches any instance of a given string; exact ' 'matches the entire field.' )