This commit is contained in:
Vignesh 2017-09-25 19:12:42 +00:00 committed by GitHub
commit 632d286006
4 changed files with 104 additions and 13 deletions

View File

@ -966,8 +966,8 @@ class FloatField(Field):
class DecimalField(Field): class DecimalField(Field):
default_error_messages = { default_error_messages = {
'invalid': _('A valid number is required.'), 'invalid': _('A valid number is required.'),
'max_value': _('Ensure this value is less than or equal to {max_value}.'), 'max_value': _('Ensure this value is less than or equal to %(limit_value)s.'),
'min_value': _('Ensure this value is greater than or equal to {min_value}.'), 'min_value': _('Ensure this value is greater than or equal to %(limit_value)s.'),
'max_digits': _('Ensure that there are no more than {max_digits} digits in total.'), '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_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.'), 'max_whole_digits': _('Ensure that there are no more than {max_whole_digits} digits before the decimal point.'),
@ -996,11 +996,9 @@ class DecimalField(Field):
super(DecimalField, self).__init__(**kwargs) super(DecimalField, self).__init__(**kwargs)
if self.max_value is not None: if self.max_value is not None:
message = self.error_messages['max_value'].format(max_value=self.max_value) self.validators.append(MaxValueValidator(self.max_value, message=self.error_messages['max_value']))
self.validators.append(MaxValueValidator(self.max_value, message=message))
if self.min_value is not None: if self.min_value is not None:
message = self.error_messages['min_value'].format(min_value=self.min_value) self.validators.append(MinValueValidator(self.min_value, message=self.error_messages['min_value']))
self.validators.append(MinValueValidator(self.min_value, message=message))
def to_internal_value(self, data): def to_internal_value(self, data):
""" """

View File

@ -127,12 +127,13 @@ def get_field_kwargs(field_name, model_field):
else: else:
# Ensure that max_value is passed explicitly as a keyword arg, # Ensure that max_value is passed explicitly as a keyword arg,
# rather than as a validator. # rather than as a validator.
max_value = next(( max_value, message = next((
validator.limit_value for validator in validator_kwarg (validator.limit_value, validator.message) for validator in validator_kwarg
if isinstance(validator, validators.MaxValueValidator) if isinstance(validator, validators.MaxValueValidator)
), None) ), (None, None))
if max_value is not None and isinstance(model_field, NUMERIC_FIELD_TYPES): if max_value is not None and isinstance(model_field, NUMERIC_FIELD_TYPES):
kwargs['max_value'] = max_value kwargs['max_value'] = max_value
kwargs['error_messages'] = {'max_value': message}
validator_kwarg = [ validator_kwarg = [
validator for validator in validator_kwarg validator for validator in validator_kwarg
if not isinstance(validator, validators.MaxValueValidator) if not isinstance(validator, validators.MaxValueValidator)
@ -140,12 +141,13 @@ def get_field_kwargs(field_name, model_field):
# Ensure that min_value is passed explicitly as a keyword arg, # Ensure that min_value is passed explicitly as a keyword arg,
# rather than as a validator. # rather than as a validator.
min_value = next(( min_value, message = next((
validator.limit_value for validator in validator_kwarg (validator.limit_value, validator.message) for validator in validator_kwarg
if isinstance(validator, validators.MinValueValidator) if isinstance(validator, validators.MinValueValidator)
), None) ), (None, None))
if min_value is not None and isinstance(model_field, NUMERIC_FIELD_TYPES): if min_value is not None and isinstance(model_field, NUMERIC_FIELD_TYPES):
kwargs['min_value'] = min_value kwargs['min_value'] = min_value
kwargs.setdefault('error_messages', {}).update(min_value=message)
validator_kwarg = [ validator_kwarg = [
validator for validator in validator_kwarg validator for validator in validator_kwarg
if not isinstance(validator, validators.MinValueValidator) if not isinstance(validator, validators.MinValueValidator)

View File

@ -200,7 +200,7 @@ class TestRegularFieldMappings(TestCase):
expected = dedent(""" expected = dedent("""
TestSerializer(): TestSerializer():
id = IntegerField(label='ID', read_only=True) id = IntegerField(label='ID', read_only=True)
value_limit_field = IntegerField(max_value=10, min_value=1) value_limit_field = IntegerField(error_messages={'max_value': 'Ensure this value is less than or equal to %(limit_value)s.', 'min_value': 'Ensure this value is greater than or equal to %(limit_value)s.'}, max_value=10, min_value=1)
length_limit_field = CharField(max_length=12, min_length=3) length_limit_field = CharField(max_length=12, min_length=3)
blank_field = CharField(allow_blank=True, max_length=10, required=False) blank_field = CharField(allow_blank=True, max_length=10, required=False)
null_field = IntegerField(allow_null=True, required=False) null_field = IntegerField(allow_null=True, required=False)
@ -214,6 +214,9 @@ class TestRegularFieldMappings(TestCase):
expected = expected.replace( expected = expected.replace(
"('red', 'Red'), ('blue', 'Blue'), ('green', 'Green')", "('red', 'Red'), ('blue', 'Blue'), ('green', 'Green')",
"(u'red', u'Red'), (u'blue', u'Blue'), (u'green', u'Green')" "(u'red', u'Red'), (u'blue', u'Blue'), (u'green', u'Green')"
).replace(
"{'max_value': 'Ensure this value is less than or equal to %(limit_value)s.', 'min_value': 'Ensure this value is greater than or equal to %(limit_value)s.'}",
"{'max_value': u'Ensure this value is less than or equal to %(limit_value)s.', 'min_value': u'Ensure this value is greater than or equal to %(limit_value)s.'}"
) )
self.assertEqual(unicode_repr(TestSerializer()), expected) self.assertEqual(unicode_repr(TestSerializer()), expected)

View File

@ -1,6 +1,7 @@
import datetime import datetime
import pytest import pytest
from django.core.validators import MinValueValidator, MaxValueValidator, URLValidator, EmailValidator, MinLengthValidator, MaxLengthValidator
from django.db import DataError, models from django.db import DataError, models
from django.test import TestCase from django.test import TestCase
@ -563,3 +564,90 @@ class ValidatorsTests(TestCase):
date_field='bar') date_field='bar')
with pytest.raises(NotImplementedError): with pytest.raises(NotImplementedError):
validator.filter_queryset(attrs=None, queryset=None) validator.filter_queryset(attrs=None, queryset=None)
class ItemModel(models.Model):
price = models.DecimalField(decimal_places=2, max_digits=10, validators=[MinValueValidator(limit_value=0, message='Price has to be >= 0.'),
MaxValueValidator(limit_value=10, message='Price has to be <= 10.')])
class ItemSerializer(serializers.ModelSerializer):
class Meta:
model = ItemModel
fields = '__all__'
class ValidatorMessageTests(TestCase):
def test_min_value_validator_message_is_copied_from_model(self):
data = {'price': -1}
s = ItemSerializer(data=data, partial=True)
s.is_valid()
assert s.errors['price'] == ['Price has to be >= 0.']
def test_max_value_validator_message_is_copied_from_model(self):
data = {'price': 11}
s = ItemSerializer(data=data, partial=True)
s.is_valid()
assert s.errors['price'] == ['Price has to be <= 10.']
def test_url_validator_message_is_copied_from_model(self):
class BlogModel(models.Model):
url = models.URLField(validators=[URLValidator(message='This URL is not valid.')])
class BlogSerializer(serializers.ModelSerializer):
class Meta:
model = BlogModel
fields = '__all__'
data = {'url': 'broken url'}
s = BlogSerializer(data=data)
s.is_valid()
assert s.errors['url'] == ['This URL is not valid.']
def test_email_validator_message_is_copied_from_model(self):
class UserModel(models.Model):
email = models.EmailField(validators=[EmailValidator(message='Please enter a valid email.')])
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = UserModel
fields = '__all__'
data = {'email': 'invalid email'}
s = UserSerializer(data=data)
s.is_valid()
assert s.errors['email'] == ['Please enter a valid email.']
def test_min_length_validator_message_is_copied_from_model(self):
class Review(models.Model):
text = models.CharField(max_length=100, validators=[MinLengthValidator(limit_value=5, message='This is too short.')])
class ReviewSerializer(serializers.ModelSerializer):
class Meta:
model = Review
fields = '__all__'
data = {'text': 'Hi'}
s = ReviewSerializer(data=data)
s.is_valid()
assert s.errors['text'] == ['This is too short.']
def test_max_length_validator_message_is_copied_from_model(self):
# Added this test because was expecting is_valid() to be false but it is not.
# Will investigate further
class Post(models.Model):
text = models.CharField(max_length=100, validators=[MaxLengthValidator(limit_value=1, message='This is too long.')])
class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = '__all__'
data = {'text': 'A very long text'}
s = PostSerializer(data=data)
assert not s.is_valid()