Commit 49b4596c authored by Eduard Stepanov's avatar Eduard Stepanov Committed by Tim Graham
Browse files

Fixed #26786 -- Avoided redundant max value validators on integer fields.

parent c9ae09ad
Loading
Loading
Loading
Loading
+12 −4
Original line number Diff line number Diff line
@@ -1812,14 +1812,22 @@ class IntegerField(Field):
    def validators(self):
        # These validators can't be added at field initialization time since
        # they're based on values retrieved from `connection`.
        range_validators = []
        validators_ = super(IntegerField, self).validators
        internal_type = self.get_internal_type()
        min_value, max_value = connection.ops.integer_field_range(internal_type)
        if min_value is not None:
            range_validators.append(validators.MinValueValidator(min_value))
            for validator in validators_:
                if isinstance(validator, validators.MinValueValidator) and validator.limit_value >= min_value:
                    break
            else:
                validators_.append(validators.MinValueValidator(min_value))
        if max_value is not None:
            range_validators.append(validators.MaxValueValidator(max_value))
        return super(IntegerField, self).validators + range_validators
            for validator in validators_:
                if isinstance(validator, validators.MaxValueValidator) and validator.limit_value <= max_value:
                    break
            else:
                validators_.append(validators.MaxValueValidator(max_value))
        return validators_

    def get_prep_value(self, value):
        value = super(IntegerField, self).get_prep_value(value)
+29 −0
Original line number Diff line number Diff line
@@ -90,6 +90,35 @@ class IntegerFieldTests(TestCase):
            instance.value = max_value
            instance.full_clean()

    def test_redundant_backend_range_validators(self):
        """
        If there are stricter validators than the ones from the database
        backend then the backend validators aren't added.
        """
        min_backend_value, max_backend_value = self.backend_range

        if min_backend_value is not None:
            min_custom_value = min_backend_value + 1
            ranged_value_field = self.model._meta.get_field('value').__class__(
                validators=[validators.MinValueValidator(min_custom_value)]
            )
            field_range_message = validators.MinValueValidator.message % {
                'limit_value': min_custom_value,
            }
            with self.assertRaisesMessage(ValidationError, "[%r]" % field_range_message):
                ranged_value_field.run_validators(min_backend_value - 1)

        if max_backend_value is not None:
            max_custom_value = max_backend_value - 1
            ranged_value_field = self.model._meta.get_field('value').__class__(
                validators=[validators.MaxValueValidator(max_custom_value)]
            )
            field_range_message = validators.MaxValueValidator.message % {
                'limit_value': max_custom_value,
            }
            with self.assertRaisesMessage(ValidationError, "[%r]" % field_range_message):
                ranged_value_field.run_validators(max_backend_value + 1)

    def test_types(self):
        instance = self.model(value=0)
        self.assertIsInstance(instance.value, six.integer_types)