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):
default_error_messages = {
'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}.'),
'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_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.'),
@ -996,11 +996,9 @@ class DecimalField(Field):
super(DecimalField, self).__init__(**kwargs)
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=message))
self.validators.append(MaxValueValidator(self.max_value, message=self.error_messages['max_value']))
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=message))
self.validators.append(MinValueValidator(self.min_value, message=self.error_messages['min_value']))
def to_internal_value(self, data):
"""

View File

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

View File

@ -200,7 +200,7 @@ class TestRegularFieldMappings(TestCase):
expected = dedent("""
TestSerializer():
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)
blank_field = CharField(allow_blank=True, max_length=10, required=False)
null_field = IntegerField(allow_null=True, required=False)
@ -214,6 +214,9 @@ class TestRegularFieldMappings(TestCase):
expected = expected.replace(
"('red', 'Red'), ('blue', 'Blue'), ('green', '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)

View File

@ -1,6 +1,7 @@
import datetime
import pytest
from django.core.validators import MinValueValidator, MaxValueValidator, URLValidator, EmailValidator, MinLengthValidator, MaxLengthValidator
from django.db import DataError, models
from django.test import TestCase
@ -563,3 +564,90 @@ class ValidatorsTests(TestCase):
date_field='bar')
with pytest.raises(NotImplementedError):
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()