From 818bbf0d002f4edf18ebf851b667cfeca1cd1f0e Mon Sep 17 00:00:00 2001 From: Arthur Date: Tue, 20 Sep 2022 15:40:43 -0700 Subject: [PATCH] 10348 add decimal custom field --- netbox/extras/models/customfields.py | 4 ++-- netbox/extras/tests/test_customfields.py | 13 +++++++------ netbox/utilities/filters.py | 6 +++++- 3 files changed, 14 insertions(+), 9 deletions(-) diff --git a/netbox/extras/models/customfields.py b/netbox/extras/models/customfields.py index 6a5c682bcf2..56cbf6b4e9e 100644 --- a/netbox/extras/models/customfields.py +++ b/netbox/extras/models/customfields.py @@ -438,7 +438,7 @@ def to_filter(self, lookup_expr=None): # Decimal elif self.type == CustomFieldTypeChoices.TYPE_DECIMAL: - filter_class = filters.MultiValueNumberFilter + filter_class = filters.MultiValueDecimalFilter # Boolean elif self.type == CustomFieldTypeChoices.TYPE_BOOLEAN: @@ -499,7 +499,7 @@ def validate(self, value): # Validate decimal elif self.type == CustomFieldTypeChoices.TYPE_DECIMAL: - if type(value) is not decimal.Decimal: + if type(value) is not decimal.Decimal and type(value) is not str: raise ValidationError("Value must be a decimal.") converted = decimal.Decimal(value) diff --git a/netbox/extras/tests/test_customfields.py b/netbox/extras/tests/test_customfields.py index 2efb4a873ef..2754cf1bf14 100644 --- a/netbox/extras/tests/test_customfields.py +++ b/netbox/extras/tests/test_customfields.py @@ -1,3 +1,4 @@ +import decimal from django.contrib.contenttypes.models import ContentType from django.core.exceptions import ValidationError from django.urls import reverse @@ -459,7 +460,7 @@ def setUpTestData(cls): custom_fields[8].name: ['Bar', 'Baz'], custom_fields[9].name: vlans[1].pk, custom_fields[10].name: [vlans[2].pk, vlans[3].pk], - custom_fields[11].name: 456.78, + custom_fields[11].name: '456.78', } sites[1].save() @@ -476,7 +477,7 @@ def test_get_custom_fields(self): CustomFieldTypeChoices.TYPE_MULTISELECT: 'array', CustomFieldTypeChoices.TYPE_OBJECT: 'object', CustomFieldTypeChoices.TYPE_MULTIOBJECT: 'array', - CustomFieldTypeChoices.TYPE_git: 'decimal', + CustomFieldTypeChoices.TYPE_DECIMAL: 'decimal', } self.add_permissions('extras.view_customfield') @@ -610,7 +611,7 @@ def test_create_single_object_with_values(self): 'multiselect_field': ['Bar', 'Baz'], 'object_field': VLAN.objects.get(vid=2).pk, 'multiobject_field': list(VLAN.objects.filter(vid__in=[3, 4]).values_list('pk', flat=True)), - 'decimal_field': 456.78, + 'decimal_field': '456.78', }, } url = reverse('dcim-api:site-list') @@ -733,7 +734,7 @@ def test_create_multiple_objects_with_values(self): 'multiselect_field': ['Bar', 'Baz'], 'object_field': VLAN.objects.get(vid=2).pk, 'multiobject_field': list(VLAN.objects.filter(vid__in=[3, 4]).values_list('pk', flat=True)), - 'decimal_field': 456.78, + 'decimal_field': '456.78', } data = ( { @@ -829,7 +830,7 @@ def test_update_single_object_with_values(self): [obj['id'] for obj in response_cf['multiobject_field']], original_cfvs['multiobject_field'] ) - self.assertEqual(response_cf['decimal_field'], data['custom_fields']['decimal_field']) + self.assertEqual(response_cf['decimal_field'], original_cfvs['decimal_field']) # Validate database data site2.refresh_from_db() @@ -844,7 +845,7 @@ def test_update_single_object_with_values(self): self.assertEqual(site2.custom_field_data['multiselect_field'], original_cfvs['multiselect_field']) self.assertEqual(site2.custom_field_data['object_field'], original_cfvs['object_field']) self.assertEqual(site2.custom_field_data['multiobject_field'], original_cfvs['multiobject_field']) - self.assertEqual(site2.custom_field_data['decimal_field'], data['custom_fields']['decimal_field']) + self.assertEqual(site2.custom_field_data['decimal_field'], original_cfvs['decimal_field']) def test_minimum_maximum_values_validation(self): site2 = Site.objects.get(name='Site 2') diff --git a/netbox/utilities/filters.py b/netbox/utilities/filters.py index 543449b73e4..f73b6dacc87 100644 --- a/netbox/utilities/filters.py +++ b/netbox/utilities/filters.py @@ -23,7 +23,7 @@ def to_python(self, value): field.to_python(v) for v in value if v ] - return type('MultiValue{}'.format(field_class.__name__), (NewField,), dict()) + return type(f'MultiValue{field_class.__name__}', (NewField,), dict()) # @@ -46,6 +46,10 @@ class MultiValueNumberFilter(django_filters.MultipleChoiceFilter): field_class = multivalue_field_factory(forms.IntegerField) +class MultiValueDecimalFilter(django_filters.MultipleChoiceFilter): + field_class = multivalue_field_factory(forms.DecimalField) + + class MultiValueTimeFilter(django_filters.MultipleChoiceFilter): field_class = multivalue_field_factory(forms.TimeField)