Skip to content

Commit 0797b26

Browse files
author
John Eskew
committed
Customize validators to defer error string evaluation.
1 parent bf0fbd5 commit 0797b26

File tree

2 files changed

+70
-22
lines changed

2 files changed

+70
-22
lines changed

rest_framework/compat.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from django.template import Context, RequestContext, Template
1717
from django.utils import six
1818
from django.views.generic import View
19+
from django.core.exceptions import ValidationError
1920

2021

2122
try:
@@ -27,6 +28,10 @@
2728
NoReverseMatch, RegexURLPattern, RegexURLResolver, ResolverMatch, Resolver404, get_script_prefix, reverse, reverse_lazy, resolve
2829
)
2930

31+
from django.core.validators import MinValueValidator as DjangoMinValueValidator
32+
from django.core.validators import MaxValueValidator as DjangoMaxValueValidator
33+
from django.core.validators import MinLengthValidator as DjangoMinLengthValidator
34+
from django.core.validators import MaxLengthValidator as DjangoMaxLengthValidator
3035

3136
try:
3237
import urlparse # Python 2.x
@@ -293,6 +298,22 @@ def pygments_css(style):
293298
except ImportError:
294299
DecimalValidator = None
295300

301+
class CustomValidatorMessage(object):
302+
def __init__(self, *args, **kwargs):
303+
self.message = kwargs.pop('message', self.message)
304+
super(CustomValidatorMessage, self).__init__(*args, **kwargs)
305+
306+
class MinValueValidator(CustomValidatorMessage, DjangoMinValueValidator):
307+
pass
308+
309+
class MaxValueValidator(CustomValidatorMessage, DjangoMaxValueValidator):
310+
pass
311+
312+
class MinLengthValidator(CustomValidatorMessage, DjangoMinLengthValidator):
313+
pass
314+
315+
class MaxLengthValidator(CustomValidatorMessage, DjangoMaxLengthValidator):
316+
pass
296317

297318
def set_rollback():
298319
if hasattr(transaction, 'set_rollback'):

rest_framework/fields.py

Lines changed: 49 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@
1313
from django.core.exceptions import ValidationError as DjangoValidationError
1414
from django.core.exceptions import ObjectDoesNotExist
1515
from django.core.validators import (
16-
EmailValidator, MaxLengthValidator, MaxValueValidator, MinLengthValidator,
17-
MinValueValidator, RegexValidator, URLValidator, ip_address_validators
16+
EmailValidator, RegexValidator, URLValidator, ip_address_validators
1817
)
1918
from django.forms import FilePathField as DjangoFilePathField
2019
from django.forms import ImageField as DjangoImageField
@@ -25,14 +24,15 @@
2524
from django.utils.duration import duration_string
2625
from django.utils.encoding import is_protected_type, smart_text
2726
from django.utils.formats import localize_input, sanitize_separators
27+
from django.utils.functional import lazy
2828
from django.utils.ipv6 import clean_ipv6_address
2929
from django.utils.timezone import utc
3030
from django.utils.translation import ugettext_lazy as _
3131

3232
from rest_framework import ISO_8601
3333
from rest_framework.compat import (
34-
InvalidTimeError, get_remote_field, unicode_repr, unicode_to_repr,
35-
value_from_object
34+
InvalidTimeError, get_remote_field, unicode_repr, unicode_to_repr, value_from_object,
35+
MaxLengthValidator, MaxValueValidator, MinLengthValidator, MinValueValidator
3636
)
3737
from rest_framework.exceptions import ErrorDetail, ValidationError
3838
from rest_framework.settings import api_settings
@@ -750,11 +750,17 @@ def __init__(self, **kwargs):
750750
self.min_length = kwargs.pop('min_length', None)
751751
super(CharField, self).__init__(**kwargs)
752752
if self.max_length is not None:
753-
message = self.error_messages['max_length'].format(max_length=self.max_length)
754-
self.validators.append(MaxLengthValidator(self.max_length, message=message))
753+
message = lazy(
754+
self.error_messages['max_length'].format,
755+
six.text_type)(max_length=self.max_length)
756+
self.validators.append(
757+
MaxLengthValidator(self.max_length, message=message))
755758
if self.min_length is not None:
756-
message = self.error_messages['min_length'].format(min_length=self.min_length)
757-
self.validators.append(MinLengthValidator(self.min_length, message=message))
759+
message = lazy(
760+
self.error_messages['min_length'].format,
761+
six.text_type)(min_length=self.min_length)
762+
self.validators.append(
763+
MinLengthValidator(self.min_length, message=message))
758764

759765
def run_validation(self, data=empty):
760766
# Test for the empty string here so that it does not get validated,
@@ -909,11 +915,17 @@ def __init__(self, **kwargs):
909915
self.min_value = kwargs.pop('min_value', None)
910916
super(IntegerField, self).__init__(**kwargs)
911917
if self.max_value is not None:
912-
message = self.error_messages['max_value'].format(max_value=self.max_value)
913-
self.validators.append(MaxValueValidator(self.max_value, message=message))
918+
message = lazy(
919+
self.error_messages['max_value'].format,
920+
six.text_type)(max_value=self.max_value)
921+
self.validators.append(
922+
MaxValueValidator(self.max_value, message=message))
914923
if self.min_value is not None:
915-
message = self.error_messages['min_value'].format(min_value=self.min_value)
916-
self.validators.append(MinValueValidator(self.min_value, message=message))
924+
message = lazy(
925+
self.error_messages['min_value'].format,
926+
six.text_type)(min_value=self.min_value)
927+
self.validators.append(
928+
MinValueValidator(self.min_value, message=message))
917929

918930
def to_internal_value(self, data):
919931
if isinstance(data, six.text_type) and len(data) > self.MAX_STRING_LENGTH:
@@ -943,11 +955,17 @@ def __init__(self, **kwargs):
943955
self.min_value = kwargs.pop('min_value', None)
944956
super(FloatField, self).__init__(**kwargs)
945957
if self.max_value is not None:
946-
message = self.error_messages['max_value'].format(max_value=self.max_value)
947-
self.validators.append(MaxValueValidator(self.max_value, message=message))
958+
message = lazy(
959+
self.error_messages['max_value'].format,
960+
six.text_type)(max_value=self.max_value)
961+
self.validators.append(
962+
MaxValueValidator(self.max_value, message=message))
948963
if self.min_value is not None:
949-
message = self.error_messages['min_value'].format(min_value=self.min_value)
950-
self.validators.append(MinValueValidator(self.min_value, message=message))
964+
message = lazy(
965+
self.error_messages['min_value'].format,
966+
six.text_type)(min_value=self.min_value)
967+
self.validators.append(
968+
MinValueValidator(self.min_value, message=message))
951969

952970
def to_internal_value(self, data):
953971

@@ -996,11 +1014,17 @@ def __init__(self, max_digits, decimal_places, coerce_to_string=None, max_value=
9961014
super(DecimalField, self).__init__(**kwargs)
9971015

9981016
if self.max_value is not None:
999-
message = self.error_messages['max_value'].format(max_value=self.max_value)
1000-
self.validators.append(MaxValueValidator(self.max_value, message=message))
1017+
message = lazy(
1018+
self.error_messages['max_value'].format,
1019+
six.text_type)(max_value=self.max_value)
1020+
self.validators.append(
1021+
MaxValueValidator(self.max_value, message=message))
10011022
if self.min_value is not None:
1002-
message = self.error_messages['min_value'].format(min_value=self.min_value)
1003-
self.validators.append(MinValueValidator(self.min_value, message=message))
1023+
message = lazy(
1024+
self.error_messages['min_value'].format,
1025+
six.text_type)(min_value=self.min_value)
1026+
self.validators.append(
1027+
MinValueValidator(self.min_value, message=message))
10041028

10051029
def to_internal_value(self, data):
10061030
"""
@@ -1797,8 +1821,11 @@ def __init__(self, model_field, **kwargs):
17971821
max_length = kwargs.pop('max_length', None)
17981822
super(ModelField, self).__init__(**kwargs)
17991823
if max_length is not None:
1800-
message = self.error_messages['max_length'].format(max_length=max_length)
1801-
self.validators.append(MaxLengthValidator(max_length, message=message))
1824+
message = lazy(
1825+
self.error_messages['max_length'].format,
1826+
six.text_type)(max_length=self.max_length)
1827+
self.validators.append(
1828+
MaxLengthValidator(self.max_length, message=message))
18021829

18031830
def to_internal_value(self, data):
18041831
rel = get_remote_field(self.model_field, default=None)

0 commit comments

Comments
 (0)