aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--rest_framework/fields.py32
-rw-r--r--tests/test_fields.py93
2 files changed, 107 insertions, 18 deletions
diff --git a/rest_framework/fields.py b/rest_framework/fields.py
index db75ddf9..35bd5c4b 100644
--- a/rest_framework/fields.py
+++ b/rest_framework/fields.py
@@ -12,6 +12,7 @@ from rest_framework.utils import html, representation, humanize_datetime
import datetime
import decimal
import inspect
+import re
class empty:
@@ -325,7 +326,11 @@ class EmailField(CharField):
default_error_messages = {
'invalid': _('Enter a valid email address.')
}
- default_validators = [validators.validate_email]
+
+ def __init__(self, **kwargs):
+ super(EmailField, self).__init__(**kwargs)
+ validator = validators.EmailValidator(message=self.error_messages['invalid'])
+ self.validators = [validator] + self.validators
def to_internal_value(self, data):
if data == '' and not self.allow_blank:
@@ -341,26 +346,37 @@ class EmailField(CharField):
class RegexField(CharField):
+ default_error_messages = {
+ 'invalid': _('This value does not match the required pattern.')
+ }
+
def __init__(self, regex, **kwargs):
- kwargs['validators'] = (
- [validators.RegexValidator(regex)] +
- kwargs.get('validators', [])
- )
super(RegexField, self).__init__(**kwargs)
+ validator = validators.RegexValidator(regex, message=self.error_messages['invalid'])
+ self.validators = [validator] + self.validators
class SlugField(CharField):
default_error_messages = {
'invalid': _("Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens.")
}
- default_validators = [validators.validate_slug]
+
+ def __init__(self, **kwargs):
+ super(SlugField, self).__init__(**kwargs)
+ slug_regex = re.compile(r'^[-a-zA-Z0-9_]+$')
+ validator = validators.RegexValidator(slug_regex, message=self.error_messages['invalid'])
+ self.validators = [validator] + self.validators
class URLField(CharField):
default_error_messages = {
'invalid': _("Enter a valid URL.")
}
- default_validators = [validators.URLValidator()]
+
+ def __init__(self, **kwargs):
+ super(URLField, self).__init__(**kwargs)
+ validator = validators.URLValidator(message=self.error_messages['invalid'])
+ self.validators = [validator] + self.validators
# Number types...
@@ -642,7 +658,7 @@ class TimeField(Field):
self.input_formats = input_formats if input_formats is not None else self.input_formats
super(TimeField, self).__init__(*args, **kwargs)
- def from_native(self, value):
+ def to_internal_value(self, value):
if value in (None, ''):
return None
diff --git a/tests/test_fields.py b/tests/test_fields.py
index 6ec18041..ae7f1919 100644
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -26,16 +26,7 @@ class ValidAndInvalidValues:
assert exc_info.value.messages == expected_failure
-class TestCharField(ValidAndInvalidValues):
- valid_mappings = {
- 1: '1',
- 'abc': 'abc'
- }
- invalid_mappings = {
- '': ['This field may not be blank.']
- }
- field = fields.CharField()
-
+# Boolean types...
class TestBooleanField(ValidAndInvalidValues):
valid_mappings = {
@@ -54,6 +45,60 @@ class TestBooleanField(ValidAndInvalidValues):
field = fields.BooleanField()
+# String types...
+
+class TestCharField(ValidAndInvalidValues):
+ valid_mappings = {
+ 1: '1',
+ 'abc': 'abc'
+ }
+ invalid_mappings = {
+ '': ['This field may not be blank.']
+ }
+ field = fields.CharField()
+
+
+class TestEmailField(ValidAndInvalidValues):
+ valid_mappings = {
+ 'example@example.com': 'example@example.com',
+ ' example@example.com ': 'example@example.com',
+ }
+ invalid_mappings = {
+ 'example.com': ['Enter a valid email address.']
+ }
+ field = fields.EmailField()
+
+
+class TestRegexField(ValidAndInvalidValues):
+ valid_mappings = {
+ 'a9': 'a9',
+ }
+ invalid_mappings = {
+ 'A9': ["This value does not match the required pattern."]
+ }
+ field = fields.RegexField(regex='[a-z][0-9]')
+
+
+class TestSlugField(ValidAndInvalidValues):
+ valid_mappings = {
+ 'slug-99': 'slug-99',
+ }
+ invalid_mappings = {
+ 'slug 99': ["Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."]
+ }
+ field = fields.SlugField()
+
+
+class TestURLField(ValidAndInvalidValues):
+ valid_mappings = {
+ 'http://example.com': 'http://example.com',
+ }
+ invalid_mappings = {
+ 'example.com': ['Enter a valid URL.']
+ }
+ field = fields.URLField()
+
+
# Number types...
class TestIntegerField(ValidAndInvalidValues):
@@ -249,6 +294,34 @@ class TestNaiveDateTimeField(ValidAndInvalidValues):
field = fields.DateTimeField(default_timezone=None)
+class TestTimeField(ValidAndInvalidValues):
+ """
+ Valid and invalid values for `TimeField`.
+ """
+ valid_mappings = {
+ '13:00': datetime.time(13, 00),
+ datetime.time(13, 00): datetime.time(13, 00),
+ }
+ invalid_mappings = {
+ 'abc': ['Time has wrong format. Use one of these formats instead: hh:mm[:ss[.uuuuuu]]'],
+ '99:99': ['Time has wrong format. Use one of these formats instead: hh:mm[:ss[.uuuuuu]]'],
+ }
+ field = fields.TimeField()
+
+
+class TestCustomInputFormatTimeField(ValidAndInvalidValues):
+ """
+ Valid and invalid values for `TimeField` with a custom input format.
+ """
+ valid_mappings = {
+ '1:00pm': datetime.time(13, 00),
+ }
+ invalid_mappings = {
+ '13:00': ['Time has wrong format. Use one of these formats instead: hh:mm[AM|PM]'],
+ }
+ field = fields.TimeField(input_formats=['%I:%M%p'])
+
+
# Choice types...
class TestChoiceField(ValidAndInvalidValues):