Min/MaxValue/LengthValidator now defer the message formatting and able to handle new string format.

This commit is contained in:
Xavier Ordoquy 2015-09-23 17:55:56 +02:00
parent 87aff642fb
commit 6007bc7d9d
2 changed files with 49 additions and 34 deletions

View File

@ -11,6 +11,8 @@ from django.conf import settings
from django.db import connection, transaction from django.db import connection, transaction
from django.utils import six from django.utils import six
from django.views.generic import View from django.views.generic import View
from django.core.exceptions import ValidationError
try: try:
import importlib # Available in Python 3.1+ import importlib # Available in Python 3.1+
@ -109,39 +111,43 @@ def get_model_name(model_cls):
return model_cls._meta.module_name return model_cls._meta.module_name
# MinValueValidator, MaxValueValidator et al. only accept `message` in 1.8+ from django.core.validators import MinValueValidator
if django.VERSION >= (1, 8): from django.core.validators import MaxValueValidator
from django.core.validators import MinValueValidator, MaxValueValidator from django.core.validators import MinLengthValidator
from django.core.validators import MinLengthValidator, MaxLengthValidator from django.core.validators import MaxLengthValidator
else:
from django.core.validators import MinValueValidator as DjangoMinValueValidator
from django.core.validators import MaxValueValidator as DjangoMaxValueValidator
from django.core.validators import MinLengthValidator as DjangoMinLengthValidator
from django.core.validators import MaxLengthValidator as DjangoMaxLengthValidator
class MinValueValidator(DjangoMinValueValidator): class CustomValidatorMessage(object):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.message = kwargs.pop('message', self.message) self.message = kwargs.pop('message', self.message)
super(MinValueValidator, self).__init__(*args, **kwargs) self.format = kwargs.pop('string_format', '%')
super(CustomValidatorMessage, self).__init__(*args, **kwargs)
def __call__(self, value):
cleaned = self.clean(value)
params = {'limit_value': self.limit_value, 'show_value': cleaned, 'value': value}
if self.compare(cleaned, self.limit_value):
message = self.message
if self.format == '{':
args = {self.code: self.limit_value}
message = message.format(**args)
raise ValidationError(message, code=self.code, params=params)
class MaxValueValidator(DjangoMaxValueValidator): class MinValueValidator(CustomValidatorMessage, MinValueValidator):
def __init__(self, *args, **kwargs): pass
self.message = kwargs.pop('message', self.message)
super(MaxValueValidator, self).__init__(*args, **kwargs)
class MinLengthValidator(DjangoMinLengthValidator): class MaxValueValidator(CustomValidatorMessage, MaxValueValidator):
def __init__(self, *args, **kwargs): pass
self.message = kwargs.pop('message', self.message)
super(MinLengthValidator, self).__init__(*args, **kwargs)
class MaxLengthValidator(DjangoMaxLengthValidator): class MinLengthValidator(CustomValidatorMessage, MinLengthValidator):
def __init__(self, *args, **kwargs): pass
self.message = kwargs.pop('message', self.message)
super(MaxLengthValidator, self).__init__(*args, **kwargs)
class MaxLengthValidator(CustomValidatorMessage, MaxLengthValidator):
pass
# URLValidator only accepts `message` in 1.6+ # URLValidator only accepts `message` in 1.6+

View File

@ -675,9 +675,11 @@ class CharField(Field):
self.min_length = kwargs.pop('min_length', None) self.min_length = kwargs.pop('min_length', None)
super(CharField, self).__init__(**kwargs) super(CharField, self).__init__(**kwargs)
if self.max_length is not None: if self.max_length is not None:
self.validators.append(MaxLengthValidator(self.max_length)) message = self.error_messages['max_length']
self.validators.append(MaxLengthValidator(self.max_length, message=message, string_format='{'))
if self.min_length is not None: if self.min_length is not None:
self.validators.append(MinLengthValidator(self.min_length)) message = self.error_messages['min_length']
self.validators.append(MinLengthValidator(self.min_length, message=message, string_format='{'))
def run_validation(self, data=empty): def run_validation(self, data=empty):
# Test for the empty string here so that it does not get validated, # Test for the empty string here so that it does not get validated,
@ -818,9 +820,11 @@ class IntegerField(Field):
self.min_value = kwargs.pop('min_value', None) self.min_value = kwargs.pop('min_value', None)
super(IntegerField, self).__init__(**kwargs) super(IntegerField, self).__init__(**kwargs)
if self.max_value is not None: if self.max_value is not None:
self.validators.append(MaxValueValidator(self.max_value)) message = self.error_messages['max_value']
self.validators.append(MaxValueValidator(self.max_value, message=message, string_format='{'))
if self.min_value is not None: if self.min_value is not None:
self.validators.append(MinValueValidator(self.min_value)) message = self.error_messages['min_value']
self.validators.append(MinValueValidator(self.min_value, message=message, string_format='{'))
def to_internal_value(self, data): def to_internal_value(self, data):
if isinstance(data, six.text_type) and len(data) > self.MAX_STRING_LENGTH: if isinstance(data, six.text_type) and len(data) > self.MAX_STRING_LENGTH:
@ -850,9 +854,11 @@ class FloatField(Field):
self.min_value = kwargs.pop('min_value', None) self.min_value = kwargs.pop('min_value', None)
super(FloatField, self).__init__(**kwargs) super(FloatField, self).__init__(**kwargs)
if self.max_value is not None: if self.max_value is not None:
self.validators.append(MaxValueValidator(self.max_value)) message = self.error_messages['max_value']
self.validators.append(MaxValueValidator(self.max_value, message=message, string_format='{'))
if self.min_value is not None: if self.min_value is not None:
self.validators.append(MinValueValidator(self.min_value)) message = self.error_messages['min_value']
self.validators.append(MinValueValidator(self.min_value, message=message, string_format='{'))
def to_internal_value(self, data): def to_internal_value(self, data):
if isinstance(data, six.text_type) and len(data) > self.MAX_STRING_LENGTH: if isinstance(data, six.text_type) and len(data) > self.MAX_STRING_LENGTH:
@ -897,9 +903,11 @@ 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:
self.validators.append(MaxValueValidator(self.max_value)) message = self.error_messages['max_value']
self.validators.append(MaxValueValidator(self.max_value, message=message, string_format='{'))
if self.min_value is not None: if self.min_value is not None:
self.validators.append(MinValueValidator(self.min_value)) message = self.error_messages['min_value']
self.validators.append(MinValueValidator(self.min_value, message=message, string_format='{'))
def to_internal_value(self, data): def to_internal_value(self, data):
""" """
@ -1598,7 +1606,8 @@ class ModelField(Field):
max_length = kwargs.pop('max_length', None) max_length = kwargs.pop('max_length', None)
super(ModelField, self).__init__(**kwargs) super(ModelField, self).__init__(**kwargs)
if max_length is not None: if max_length is not None:
self.validators.append(MaxLengthValidator(max_length)) message = self.error_messages['max_length']
self.validators.append(MaxLengthValidator(max_length, message=message, string_format='{'))
def to_internal_value(self, data): def to_internal_value(self, data):
rel = getattr(self.model_field, 'rel', None) rel = getattr(self.model_field, 'rel', None)