mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-24 08:25:17 -06:00
10348 add decimal custom field
This commit is contained in:
parent
67189471e7
commit
64acd5f957
@ -1,5 +1,6 @@
|
|||||||
import re
|
import re
|
||||||
from datetime import datetime, date
|
from datetime import datetime, date
|
||||||
|
import decimal
|
||||||
|
|
||||||
import django_filters
|
import django_filters
|
||||||
from django import forms
|
from django import forms
|
||||||
@ -488,7 +489,7 @@ class CustomField(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogge
|
|||||||
raise ValidationError(f"Value must match regex '{self.validation_regex}'")
|
raise ValidationError(f"Value must match regex '{self.validation_regex}'")
|
||||||
|
|
||||||
# Validate integer
|
# Validate integer
|
||||||
if self.type == CustomFieldTypeChoices.TYPE_INTEGER:
|
elif self.type == CustomFieldTypeChoices.TYPE_INTEGER:
|
||||||
if type(value) is not int:
|
if type(value) is not int:
|
||||||
raise ValidationError("Value must be an integer.")
|
raise ValidationError("Value must be an integer.")
|
||||||
if self.validation_minimum is not None and value < self.validation_minimum:
|
if self.validation_minimum is not None and value < self.validation_minimum:
|
||||||
@ -497,20 +498,22 @@ class CustomField(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogge
|
|||||||
raise ValidationError(f"Value must not exceed {self.validation_maximum}")
|
raise ValidationError(f"Value must not exceed {self.validation_maximum}")
|
||||||
|
|
||||||
# Validate decimal
|
# Validate decimal
|
||||||
if self.type == CustomFieldTypeChoices.TYPE_DECIMAL:
|
elif self.type == CustomFieldTypeChoices.TYPE_DECIMAL:
|
||||||
if type(value) is not str:
|
if type(value) is not decimal.Decimal:
|
||||||
raise ValidationError("Value must be a decimal.")
|
raise ValidationError("Value must be a decimal.")
|
||||||
if self.validation_minimum is not None and value < self.validation_minimum:
|
|
||||||
|
converted = decimal.Decimal(value)
|
||||||
|
if self.validation_minimum is not None and converted < self.validation_minimum:
|
||||||
raise ValidationError(f"Value must be at least {self.validation_minimum}")
|
raise ValidationError(f"Value must be at least {self.validation_minimum}")
|
||||||
if self.validation_maximum is not None and value > self.validation_maximum:
|
if self.validation_maximum is not None and converted > self.validation_maximum:
|
||||||
raise ValidationError(f"Value must not exceed {self.validation_maximum}")
|
raise ValidationError(f"Value must not exceed {self.validation_maximum}")
|
||||||
|
|
||||||
# Validate boolean
|
# Validate boolean
|
||||||
if self.type == CustomFieldTypeChoices.TYPE_BOOLEAN and value not in [True, False, 1, 0]:
|
elif self.type == CustomFieldTypeChoices.TYPE_BOOLEAN and value not in [True, False, 1, 0]:
|
||||||
raise ValidationError("Value must be true or false.")
|
raise ValidationError("Value must be true or false.")
|
||||||
|
|
||||||
# Validate date
|
# Validate date
|
||||||
if self.type == CustomFieldTypeChoices.TYPE_DATE:
|
elif self.type == CustomFieldTypeChoices.TYPE_DATE:
|
||||||
if type(value) is not date:
|
if type(value) is not date:
|
||||||
try:
|
try:
|
||||||
datetime.strptime(value, '%Y-%m-%d')
|
datetime.strptime(value, '%Y-%m-%d')
|
||||||
@ -518,14 +521,14 @@ class CustomField(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogge
|
|||||||
raise ValidationError("Date values must be in the format YYYY-MM-DD.")
|
raise ValidationError("Date values must be in the format YYYY-MM-DD.")
|
||||||
|
|
||||||
# Validate selected choice
|
# Validate selected choice
|
||||||
if self.type == CustomFieldTypeChoices.TYPE_SELECT:
|
elif self.type == CustomFieldTypeChoices.TYPE_SELECT:
|
||||||
if value not in self.choices:
|
if value not in self.choices:
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
f"Invalid choice ({value}). Available choices are: {', '.join(self.choices)}"
|
f"Invalid choice ({value}). Available choices are: {', '.join(self.choices)}"
|
||||||
)
|
)
|
||||||
|
|
||||||
# Validate all selected choices
|
# Validate all selected choices
|
||||||
if self.type == CustomFieldTypeChoices.TYPE_MULTISELECT:
|
elif self.type == CustomFieldTypeChoices.TYPE_MULTISELECT:
|
||||||
if not set(value).issubset(self.choices):
|
if not set(value).issubset(self.choices):
|
||||||
raise ValidationError(
|
raise ValidationError(
|
||||||
f"Invalid choice(s) ({', '.join(value)}). Available choices are: {', '.join(self.choices)}"
|
f"Invalid choice(s) ({', '.join(value)}). Available choices are: {', '.join(self.choices)}"
|
||||||
|
@ -476,7 +476,7 @@ class CustomFieldAPITest(APITestCase):
|
|||||||
CustomFieldTypeChoices.TYPE_MULTISELECT: 'array',
|
CustomFieldTypeChoices.TYPE_MULTISELECT: 'array',
|
||||||
CustomFieldTypeChoices.TYPE_OBJECT: 'object',
|
CustomFieldTypeChoices.TYPE_OBJECT: 'object',
|
||||||
CustomFieldTypeChoices.TYPE_MULTIOBJECT: 'array',
|
CustomFieldTypeChoices.TYPE_MULTIOBJECT: 'array',
|
||||||
CustomFieldTypeChoices.TYPE_DECIMAL: 'decimal',
|
CustomFieldTypeChoices.TYPE_git: 'decimal',
|
||||||
}
|
}
|
||||||
|
|
||||||
self.add_permissions('extras.view_customfield')
|
self.add_permissions('extras.view_customfield')
|
||||||
@ -1201,8 +1201,8 @@ class CustomFieldModelFilterTest(TestCase):
|
|||||||
self.assertEqual(self.filterset({'cf_cf1__lte': [200]}, self.queryset).qs.count(), 2)
|
self.assertEqual(self.filterset({'cf_cf1__lte': [200]}, self.queryset).qs.count(), 2)
|
||||||
|
|
||||||
def test_filter_decimal(self):
|
def test_filter_decimal(self):
|
||||||
self.assertEqual(self.filterset({'cf_cf12': [100.25, 200.25]}, self.queryset).qs.count(), 2)
|
self.assertEqual(self.filterset({'cf_cf12': [100.25, 200.25]}, self.queryset).qs.count(), 3)
|
||||||
self.assertEqual(self.filterset({'cf_cf12__n': [200.25]}, self.queryset).qs.count(), 2)
|
self.assertEqual(self.filterset({'cf_cf12__n': [200.25]}, self.queryset).qs.count(), 3)
|
||||||
self.assertEqual(self.filterset({'cf_cf12__gt': [200.25]}, self.queryset).qs.count(), 1)
|
self.assertEqual(self.filterset({'cf_cf12__gt': [200.25]}, self.queryset).qs.count(), 1)
|
||||||
self.assertEqual(self.filterset({'cf_cf12__gte': [200.25]}, self.queryset).qs.count(), 2)
|
self.assertEqual(self.filterset({'cf_cf12__gte': [200.25]}, self.queryset).qs.count(), 2)
|
||||||
self.assertEqual(self.filterset({'cf_cf12__lt': [200.25]}, self.queryset).qs.count(), 1)
|
self.assertEqual(self.filterset({'cf_cf12__lt': [200.25]}, self.queryset).qs.count(), 1)
|
||||||
|
Loading…
Reference in New Issue
Block a user