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.utils import six
from django.views.generic import View
from django.core.exceptions import ValidationError
try:
import importlib # Available in Python 3.1+
@ -109,39 +111,43 @@ def get_model_name(model_cls):
return model_cls._meta.module_name
# MinValueValidator, MaxValueValidator et al. only accept `message` in 1.8+
if django.VERSION >= (1, 8):
from django.core.validators import MinValueValidator, MaxValueValidator
from django.core.validators import MinLengthValidator, 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
from django.core.validators import MinValueValidator
from django.core.validators import MaxValueValidator
from django.core.validators import MinLengthValidator
from django.core.validators import MaxLengthValidator
class MinValueValidator(DjangoMinValueValidator):
def __init__(self, *args, **kwargs):
self.message = kwargs.pop('message', self.message)
super(MinValueValidator, self).__init__(*args, **kwargs)
class CustomValidatorMessage(object):
def __init__(self, *args, **kwargs):
self.message = kwargs.pop('message', self.message)
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):
def __init__(self, *args, **kwargs):
self.message = kwargs.pop('message', self.message)
super(MaxValueValidator, self).__init__(*args, **kwargs)
class MinValueValidator(CustomValidatorMessage, MinValueValidator):
pass
class MinLengthValidator(DjangoMinLengthValidator):
def __init__(self, *args, **kwargs):
self.message = kwargs.pop('message', self.message)
super(MinLengthValidator, self).__init__(*args, **kwargs)
class MaxValueValidator(CustomValidatorMessage, MaxValueValidator):
pass
class MaxLengthValidator(DjangoMaxLengthValidator):
def __init__(self, *args, **kwargs):
self.message = kwargs.pop('message', self.message)
super(MaxLengthValidator, self).__init__(*args, **kwargs)
class MinLengthValidator(CustomValidatorMessage, MinLengthValidator):
pass
class MaxLengthValidator(CustomValidatorMessage, MaxLengthValidator):
pass
# URLValidator only accepts `message` in 1.6+

View File

@ -675,9 +675,11 @@ class CharField(Field):
self.min_length = kwargs.pop('min_length', None)
super(CharField, self).__init__(**kwargs)
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:
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):
# 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)
super(IntegerField, self).__init__(**kwargs)
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:
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):
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)
super(FloatField, self).__init__(**kwargs)
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:
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):
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)
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:
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):
"""
@ -1598,7 +1606,8 @@ class ModelField(Field):
max_length = kwargs.pop('max_length', None)
super(ModelField, self).__init__(**kwargs)
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):
rel = getattr(self.model_field, 'rel', None)