diff --git a/netbox/utilities/validators.py b/netbox/utilities/validators.py index 0e896e52a..4b7529472 100644 --- a/netbox/utilities/validators.py +++ b/netbox/utilities/validators.py @@ -1,3 +1,4 @@ +import decimal import re from django.core.exceptions import ValidationError @@ -10,6 +11,7 @@ __all__ = ( 'ColorValidator', 'EnhancedURLValidator', 'ExclusionValidator', + 'MultipleOfValidator', 'validate_regex', ) @@ -54,6 +56,22 @@ class ExclusionValidator(BaseValidator): return a in b +class MultipleOfValidator(BaseValidator): + """ + Checks that a field's value is a numeric multiple of the given value. Both values are + cast as Decimals for comparison. + """ + def __init__(self, multiple): + self.multiple = decimal.Decimal(str(multiple)) + super().__init__(limit_value=None) + + def __call__(self, value): + if decimal.Decimal(str(value)) % self.multiple != 0: + raise ValidationError( + _("{value} must be a multiple of {multiple}.").format(value=value, multiple=self.multiple) + ) + + def validate_regex(value): """ Checks that the value is a valid regular expression. (Don't confuse this with RegexValidator, which *uses* a regex