mirror of
https://github.com/encode/django-rest-framework.git
synced 2024-12-01 05:54:01 +03:00
Adding more verbose validation error messages in case of both "min_value" and "max_value" limits are set.
This commit is contained in:
parent
ec29ff8a80
commit
3b4f617a2e
|
@ -931,6 +931,7 @@ class IntegerField(Field):
|
|||
'invalid': _('A valid integer is required.'),
|
||||
'max_value': _('Ensure this value is less than or equal to {max_value}.'),
|
||||
'min_value': _('Ensure this value is greater than or equal to {min_value}.'),
|
||||
'range': _('Ensure this value is in the range between {min_value} and {max_value}.'),
|
||||
'max_string_length': _('String value too large.')
|
||||
}
|
||||
MAX_STRING_LENGTH = 1000 # Guard against malicious string inputs.
|
||||
|
@ -940,14 +941,22 @@ class IntegerField(Field):
|
|||
self.max_value = kwargs.pop('max_value', None)
|
||||
self.min_value = kwargs.pop('min_value', None)
|
||||
super().__init__(**kwargs)
|
||||
|
||||
if self.min_value is not None and self.max_value is not None:
|
||||
message = lazy_format(
|
||||
self.error_messages['range'], min_value=self.min_value, max_value=self.max_value)
|
||||
else:
|
||||
message = None
|
||||
|
||||
if self.max_value is not None:
|
||||
message = lazy_format(self.error_messages['max_value'], max_value=self.max_value)
|
||||
self.validators.append(
|
||||
MaxValueValidator(self.max_value, message=message))
|
||||
MaxValueValidator(self.max_value, message=message or lazy_format(
|
||||
self.error_messages['max_value'], max_value=self.max_value)))
|
||||
|
||||
if self.min_value is not None:
|
||||
message = lazy_format(self.error_messages['min_value'], min_value=self.min_value)
|
||||
self.validators.append(
|
||||
MinValueValidator(self.min_value, message=message))
|
||||
MinValueValidator(self.min_value, message=message or lazy_format(
|
||||
self.error_messages['min_value'], min_value=self.min_value)))
|
||||
|
||||
def to_internal_value(self, data):
|
||||
if isinstance(data, str) and len(data) > self.MAX_STRING_LENGTH:
|
||||
|
@ -968,6 +977,7 @@ class FloatField(Field):
|
|||
'invalid': _('A valid number is required.'),
|
||||
'max_value': _('Ensure this value is less than or equal to {max_value}.'),
|
||||
'min_value': _('Ensure this value is greater than or equal to {min_value}.'),
|
||||
'range': _('Ensure this value is in the range between {min_value} and {max_value}.'),
|
||||
'max_string_length': _('String value too large.')
|
||||
}
|
||||
MAX_STRING_LENGTH = 1000 # Guard against malicious string inputs.
|
||||
|
@ -976,14 +986,22 @@ class FloatField(Field):
|
|||
self.max_value = kwargs.pop('max_value', None)
|
||||
self.min_value = kwargs.pop('min_value', None)
|
||||
super().__init__(**kwargs)
|
||||
|
||||
if self.min_value is not None and self.max_value is not None:
|
||||
message = lazy_format(
|
||||
self.error_messages['range'], min_value=self.min_value, max_value=self.max_value)
|
||||
else:
|
||||
message = None
|
||||
|
||||
if self.max_value is not None:
|
||||
message = lazy_format(self.error_messages['max_value'], max_value=self.max_value)
|
||||
self.validators.append(
|
||||
MaxValueValidator(self.max_value, message=message))
|
||||
MaxValueValidator(self.max_value, message=message or lazy_format(
|
||||
self.error_messages['max_value'], max_value=self.max_value)))
|
||||
|
||||
if self.min_value is not None:
|
||||
message = lazy_format(self.error_messages['min_value'], min_value=self.min_value)
|
||||
self.validators.append(
|
||||
MinValueValidator(self.min_value, message=message))
|
||||
MinValueValidator(self.min_value, message=message or lazy_format(
|
||||
self.error_messages['min_value'], min_value=self.min_value)))
|
||||
|
||||
def to_internal_value(self, data):
|
||||
|
||||
|
@ -1004,6 +1022,7 @@ class DecimalField(Field):
|
|||
'invalid': _('A valid number is required.'),
|
||||
'max_value': _('Ensure this value is less than or equal to {max_value}.'),
|
||||
'min_value': _('Ensure this value is greater than or equal to {min_value}.'),
|
||||
'range': _('Ensure this value is in the range between {min_value} and {max_value}.'),
|
||||
'max_digits': _('Ensure that there are no more than {max_digits} digits in total.'),
|
||||
'max_decimal_places': _('Ensure that there are no more than {max_decimal_places} decimal places.'),
|
||||
'max_whole_digits': _('Ensure that there are no more than {max_whole_digits} digits before the decimal point.'),
|
||||
|
@ -1031,14 +1050,21 @@ class DecimalField(Field):
|
|||
|
||||
super().__init__(**kwargs)
|
||||
|
||||
if self.min_value is not None and self.max_value is not None:
|
||||
message = lazy_format(
|
||||
self.error_messages['range'], min_value=self.min_value, max_value=self.max_value)
|
||||
else:
|
||||
message = None
|
||||
|
||||
if self.max_value is not None:
|
||||
message = lazy_format(self.error_messages['max_value'], max_value=self.max_value)
|
||||
self.validators.append(
|
||||
MaxValueValidator(self.max_value, message=message))
|
||||
MaxValueValidator(self.max_value, message=message or lazy_format(
|
||||
self.error_messages['max_value'], max_value=self.max_value)))
|
||||
|
||||
if self.min_value is not None:
|
||||
message = lazy_format(self.error_messages['min_value'], min_value=self.min_value)
|
||||
self.validators.append(
|
||||
MinValueValidator(self.min_value, message=message))
|
||||
MinValueValidator(self.min_value, message=message or lazy_format(
|
||||
self.error_messages['min_value'], min_value=self.min_value)))
|
||||
|
||||
if rounding is not None:
|
||||
valid_roundings = [v for k, v in vars(decimal).items() if k.startswith('ROUND_')]
|
||||
|
@ -1365,20 +1391,29 @@ class DurationField(Field):
|
|||
'invalid': _('Duration has wrong format. Use one of these formats instead: {format}.'),
|
||||
'max_value': _('Ensure this value is less than or equal to {max_value}.'),
|
||||
'min_value': _('Ensure this value is greater than or equal to {min_value}.'),
|
||||
'range': _('Ensure this value is in the range between {min_value} and {max_value}.'),
|
||||
}
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
self.max_value = kwargs.pop('max_value', None)
|
||||
self.min_value = kwargs.pop('min_value', None)
|
||||
super().__init__(**kwargs)
|
||||
|
||||
if self.min_value is not None and self.max_value is not None:
|
||||
message = lazy_format(
|
||||
self.error_messages['range'], min_value=self.min_value, max_value=self.max_value)
|
||||
else:
|
||||
message = None
|
||||
|
||||
if self.max_value is not None:
|
||||
message = lazy_format(self.error_messages['max_value'], max_value=self.max_value)
|
||||
self.validators.append(
|
||||
MaxValueValidator(self.max_value, message=message))
|
||||
MaxValueValidator(self.max_value, message=message or lazy_format(
|
||||
self.error_messages['max_value'], max_value=self.max_value)))
|
||||
|
||||
if self.min_value is not None:
|
||||
message = lazy_format(self.error_messages['min_value'], min_value=self.min_value)
|
||||
self.validators.append(
|
||||
MinValueValidator(self.min_value, message=message))
|
||||
MinValueValidator(self.min_value, message=message or lazy_format(
|
||||
self.error_messages['min_value'], min_value=self.min_value)))
|
||||
|
||||
def to_internal_value(self, value):
|
||||
if isinstance(value, datetime.timedelta):
|
||||
|
@ -1603,7 +1638,8 @@ class ListField(Field):
|
|||
'not_a_list': _('Expected a list of items but got type "{input_type}".'),
|
||||
'empty': _('This list may not be empty.'),
|
||||
'min_length': _('Ensure this field has at least {min_length} elements.'),
|
||||
'max_length': _('Ensure this field has no more than {max_length} elements.')
|
||||
'max_length': _('Ensure this field has no more than {max_length} elements.'),
|
||||
'range': _('Ensure this field has at least {min_length} and no more than {max_length} elements.'),
|
||||
}
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -1620,12 +1656,22 @@ class ListField(Field):
|
|||
|
||||
super().__init__(*args, **kwargs)
|
||||
self.child.bind(field_name='', parent=self)
|
||||
|
||||
if self.min_length is not None and self.max_length is not None:
|
||||
message = lazy_format(
|
||||
self.error_messages['range'], min_length=self.min_length, max_length=self.max_length)
|
||||
else:
|
||||
message = None
|
||||
|
||||
if self.max_length is not None:
|
||||
message = lazy_format(self.error_messages['max_length'], max_length=self.max_length)
|
||||
self.validators.append(MaxLengthValidator(self.max_length, message=message))
|
||||
self.validators.append(
|
||||
MaxLengthValidator(self.max_length, message=message or lazy_format(
|
||||
self.error_messages['max_length'], max_length=self.max_length)))
|
||||
|
||||
if self.min_length is not None:
|
||||
message = lazy_format(self.error_messages['min_length'], min_length=self.min_length)
|
||||
self.validators.append(MinLengthValidator(self.min_length, message=message))
|
||||
self.validators.append(
|
||||
MinLengthValidator(self.min_length, message=message or lazy_format(
|
||||
self.error_messages['min_length'], min_length=self.min_length)))
|
||||
|
||||
def get_value(self, dictionary):
|
||||
if self.field_name not in dictionary:
|
||||
|
|
|
@ -1019,15 +1019,51 @@ class TestMinMaxIntegerField(FieldValues):
|
|||
3: 3,
|
||||
}
|
||||
invalid_inputs = {
|
||||
0: ['Ensure this value is greater than or equal to 1.'],
|
||||
4: ['Ensure this value is less than or equal to 3.'],
|
||||
'0': ['Ensure this value is greater than or equal to 1.'],
|
||||
'4': ['Ensure this value is less than or equal to 3.'],
|
||||
0: ['Ensure this value is in the range between 1 and 3.'],
|
||||
4: ['Ensure this value is in the range between 1 and 3.'],
|
||||
'0': ['Ensure this value is in the range between 1 and 3.'],
|
||||
'4': ['Ensure this value is in the range between 1 and 3.'],
|
||||
}
|
||||
outputs = {}
|
||||
field = serializers.IntegerField(min_value=1, max_value=3)
|
||||
|
||||
|
||||
class TestMinIntegerField(FieldValues):
|
||||
"""
|
||||
Valid and invalid values for `IntegerField` with min limit.
|
||||
"""
|
||||
valid_inputs = {
|
||||
'1': 1,
|
||||
'3': 3,
|
||||
1: 1,
|
||||
3: 3,
|
||||
}
|
||||
invalid_inputs = {
|
||||
0: ['Ensure this value is greater than or equal to 1.'],
|
||||
'0': ['Ensure this value is greater than or equal to 1.'],
|
||||
}
|
||||
outputs = {}
|
||||
field = serializers.IntegerField(min_value=1)
|
||||
|
||||
|
||||
class TestMaxIntegerField(FieldValues):
|
||||
"""
|
||||
Valid and invalid values for `IntegerField` with max limit.
|
||||
"""
|
||||
valid_inputs = {
|
||||
'1': 1,
|
||||
'3': 3,
|
||||
1: 1,
|
||||
3: 3,
|
||||
}
|
||||
invalid_inputs = {
|
||||
4: ['Ensure this value is less than or equal to 3.'],
|
||||
'4': ['Ensure this value is less than or equal to 3.'],
|
||||
}
|
||||
outputs = {}
|
||||
field = serializers.IntegerField(max_value=3)
|
||||
|
||||
|
||||
class TestFloatField(FieldValues):
|
||||
"""
|
||||
Valid and invalid values for `FloatField`.
|
||||
|
@ -1067,15 +1103,55 @@ class TestMinMaxFloatField(FieldValues):
|
|||
3.0: 3.0,
|
||||
}
|
||||
invalid_inputs = {
|
||||
0.9: ['Ensure this value is greater than or equal to 1.'],
|
||||
3.1: ['Ensure this value is less than or equal to 3.'],
|
||||
'0.0': ['Ensure this value is greater than or equal to 1.'],
|
||||
'3.1': ['Ensure this value is less than or equal to 3.'],
|
||||
0.9: ['Ensure this value is in the range between 1 and 3.'],
|
||||
3.1: ['Ensure this value is in the range between 1 and 3.'],
|
||||
'0.0': ['Ensure this value is in the range between 1 and 3.'],
|
||||
'3.1': ['Ensure this value is in the range between 1 and 3.'],
|
||||
}
|
||||
outputs = {}
|
||||
field = serializers.FloatField(min_value=1, max_value=3)
|
||||
|
||||
|
||||
class TestMinFloatField(FieldValues):
|
||||
"""
|
||||
Valid and invalid values for `FloatField` with min limit.
|
||||
"""
|
||||
valid_inputs = {
|
||||
'1': 1,
|
||||
'3': 3,
|
||||
1: 1,
|
||||
3: 3,
|
||||
1.0: 1.0,
|
||||
3.0: 3.0,
|
||||
}
|
||||
invalid_inputs = {
|
||||
0.9: ['Ensure this value is greater than or equal to 1.'],
|
||||
'0.0': ['Ensure this value is greater than or equal to 1.'],
|
||||
}
|
||||
outputs = {}
|
||||
field = serializers.FloatField(min_value=1)
|
||||
|
||||
|
||||
class TestMaxFloatField(FieldValues):
|
||||
"""
|
||||
Valid and invalid values for `FloatField` with max limit.
|
||||
"""
|
||||
valid_inputs = {
|
||||
'1': 1,
|
||||
'3': 3,
|
||||
1: 1,
|
||||
3: 3,
|
||||
1.0: 1.0,
|
||||
3.0: 3.0,
|
||||
}
|
||||
invalid_inputs = {
|
||||
3.1: ['Ensure this value is less than or equal to 3.'],
|
||||
'3.1': ['Ensure this value is less than or equal to 3.'],
|
||||
}
|
||||
outputs = {}
|
||||
field = serializers.FloatField(max_value=3)
|
||||
|
||||
|
||||
class TestDecimalField(FieldValues):
|
||||
"""
|
||||
Valid and invalid values for `DecimalField`.
|
||||
|
@ -1124,8 +1200,8 @@ class TestMinMaxDecimalField(FieldValues):
|
|||
'20.0': Decimal('20.0'),
|
||||
}
|
||||
invalid_inputs = {
|
||||
'9.9': ['Ensure this value is greater than or equal to 10.'],
|
||||
'20.1': ['Ensure this value is less than or equal to 20.'],
|
||||
'9.9': ['Ensure this value is in the range between 10 and 20.'],
|
||||
'20.1': ['Ensure this value is in the range between 10 and 20.'],
|
||||
}
|
||||
outputs = {}
|
||||
field = serializers.DecimalField(
|
||||
|
@ -1134,6 +1210,42 @@ class TestMinMaxDecimalField(FieldValues):
|
|||
)
|
||||
|
||||
|
||||
class TestMinDecimalField(FieldValues):
|
||||
"""
|
||||
Valid and invalid values for `DecimalField` with min limit.
|
||||
"""
|
||||
valid_inputs = {
|
||||
'10.0': Decimal('10.0'),
|
||||
'20.0': Decimal('20.0'),
|
||||
}
|
||||
invalid_inputs = {
|
||||
'9.9': ['Ensure this value is greater than or equal to 10.'],
|
||||
}
|
||||
outputs = {}
|
||||
field = serializers.DecimalField(
|
||||
max_digits=3, decimal_places=1,
|
||||
min_value=10
|
||||
)
|
||||
|
||||
|
||||
class TestMaxDecimalField(FieldValues):
|
||||
"""
|
||||
Valid and invalid values for `DecimalField` with max limit.
|
||||
"""
|
||||
valid_inputs = {
|
||||
'10.0': Decimal('10.0'),
|
||||
'20.0': Decimal('20.0'),
|
||||
}
|
||||
invalid_inputs = {
|
||||
'20.1': ['Ensure this value is less than or equal to 20.'],
|
||||
}
|
||||
outputs = {}
|
||||
field = serializers.DecimalField(
|
||||
max_digits=3, decimal_places=1,
|
||||
max_value=20
|
||||
)
|
||||
|
||||
|
||||
class TestNoMaxDigitsDecimalField(FieldValues):
|
||||
field = serializers.DecimalField(
|
||||
max_value=100, min_value=0,
|
||||
|
@ -1536,14 +1648,45 @@ class TestMinMaxDurationField(FieldValues):
|
|||
86401: datetime.timedelta(days=1, seconds=1),
|
||||
}
|
||||
invalid_inputs = {
|
||||
3600: ['Ensure this value is greater than or equal to 1 day, 0:00:00.'],
|
||||
'4 08:32:01.000123': ['Ensure this value is less than or equal to 4 days, 0:00:00.'],
|
||||
'3600': ['Ensure this value is greater than or equal to 1 day, 0:00:00.'],
|
||||
3600: ['Ensure this value is in the range between 1 day, 0:00:00 and 4 days, 0:00:00.'],
|
||||
'4 08:32:01.000123': ['Ensure this value is in the range between 1 day, 0:00:00 and 4 days, 0:00:00.'],
|
||||
'3600': ['Ensure this value is in the range between 1 day, 0:00:00 and 4 days, 0:00:00.'],
|
||||
}
|
||||
outputs = {}
|
||||
field = serializers.DurationField(min_value=datetime.timedelta(days=1), max_value=datetime.timedelta(days=4))
|
||||
|
||||
|
||||
class TestMinDurationField(FieldValues):
|
||||
"""
|
||||
Valid and invalid values for `DurationField` with min limit.
|
||||
"""
|
||||
valid_inputs = {
|
||||
'3 08:32:01.000123': datetime.timedelta(days=3, hours=8, minutes=32, seconds=1, microseconds=123),
|
||||
86401: datetime.timedelta(days=1, seconds=1),
|
||||
}
|
||||
invalid_inputs = {
|
||||
3600: ['Ensure this value is greater than or equal to 1 day, 0:00:00.'],
|
||||
'3600': ['Ensure this value is greater than or equal to 1 day, 0:00:00.'],
|
||||
}
|
||||
outputs = {}
|
||||
field = serializers.DurationField(min_value=datetime.timedelta(days=1))
|
||||
|
||||
|
||||
class TestMaxDurationField(FieldValues):
|
||||
"""
|
||||
Valid and invalid values for `DurationField` with max limit.
|
||||
"""
|
||||
valid_inputs = {
|
||||
'3 08:32:01.000123': datetime.timedelta(days=3, hours=8, minutes=32, seconds=1, microseconds=123),
|
||||
86401: datetime.timedelta(days=1, seconds=1),
|
||||
}
|
||||
invalid_inputs = {
|
||||
'4 08:32:01.000123': ['Ensure this value is less than or equal to 4 days, 0:00:00.'],
|
||||
}
|
||||
outputs = {}
|
||||
field = serializers.DurationField(max_value=datetime.timedelta(days=4))
|
||||
|
||||
|
||||
class TestDurationField(FieldValues):
|
||||
"""
|
||||
Valid and invalid values for `DurationField`.
|
||||
|
@ -1989,16 +2132,43 @@ class TestEmptyListField(FieldValues):
|
|||
field = serializers.ListField(child=serializers.IntegerField(), allow_empty=False)
|
||||
|
||||
|
||||
class TestListFieldLengthLimit(FieldValues):
|
||||
class TestListFieldMinMaxLengthLimit(FieldValues):
|
||||
"""
|
||||
Valid and invalid values for `ListField` with min and max limits.
|
||||
"""
|
||||
valid_inputs = ()
|
||||
invalid_inputs = [
|
||||
((0, 1), ['Ensure this field has at least 3 elements.']),
|
||||
((0, 1, 2, 3, 4, 5), ['Ensure this field has no more than 4 elements.']),
|
||||
((0, 1), ['Ensure this field has at least 3 and no more than 4 elements.']),
|
||||
((0, 1, 2, 3, 4, 5), ['Ensure this field has at least 3 and no more than 4 elements.']),
|
||||
]
|
||||
outputs = ()
|
||||
field = serializers.ListField(child=serializers.IntegerField(), min_length=3, max_length=4)
|
||||
|
||||
|
||||
class TestListFieldMinLengthLimit(FieldValues):
|
||||
"""
|
||||
Valid and invalid values for `ListField` with min limit.
|
||||
"""
|
||||
valid_inputs = ()
|
||||
invalid_inputs = [
|
||||
((0, 1), ['Ensure this field has at least 3 elements.']),
|
||||
]
|
||||
outputs = ()
|
||||
field = serializers.ListField(child=serializers.IntegerField(), min_length=3)
|
||||
|
||||
|
||||
class TestListFieldMaxLengthLimit(FieldValues):
|
||||
"""
|
||||
Valid and invalid values for `ListField` with max limit.
|
||||
"""
|
||||
valid_inputs = ()
|
||||
invalid_inputs = [
|
||||
((0, 1, 2, 3, 4, 5), ['Ensure this field has no more than 4 elements.']),
|
||||
]
|
||||
outputs = ()
|
||||
field = serializers.ListField(child=serializers.IntegerField(), max_length=4)
|
||||
|
||||
|
||||
class TestUnvalidatedListField(FieldValues):
|
||||
"""
|
||||
Values for `ListField` with no `child` argument.
|
||||
|
|
Loading…
Reference in New Issue
Block a user