aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephan Groß2012-11-21 03:00:02 -0800
committerStephan Groß2012-11-21 03:00:02 -0800
commit196fa5e94f5348dbb3873a5c87561416b16ea013 (patch)
tree36ef44691a8f8bf4b18e080c6e2e9c470198bdfc
parent3268c67343f6fc6364a0127a7bfabeb907a4751d (diff)
parent03100168ff96dd4a09ee7c8a5a63b294abe99dfe (diff)
downloaddjango-rest-framework-196fa5e94f5348dbb3873a5c87561416b16ea013.tar.bz2
Merge pull request #436 from minddust/regex_field
added RegexField
-rw-r--r--docs/api-guide/fields.md10
-rw-r--r--docs/topics/release-notes.md7
-rw-r--r--rest_framework/fields.py29
-rw-r--r--rest_framework/tests/models.py5
-rw-r--r--rest_framework/tests/serializer.py28
5 files changed, 75 insertions, 4 deletions
diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md
index 914d0861..1d4c34cb 100644
--- a/docs/api-guide/fields.md
+++ b/docs/api-guide/fields.md
@@ -153,6 +153,16 @@ A text representation, validates the text to be a valid e-mail address.
Corresponds to `django.db.models.fields.EmailField`
+## RegexField
+
+A text representation, that validates the given value matches against a certain regular expression.
+
+Uses Django's `django.core.validators.RegexValidator` for validation.
+
+Corresponds to `django.forms.fields.RegexField`
+
+**Signature:** `RegexField(regex, max_length=None, min_length=None)`
+
## DateField
A date representation.
diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md
index 0b8a7a8f..c641a1b3 100644
--- a/docs/topics/release-notes.md
+++ b/docs/topics/release-notes.md
@@ -6,10 +6,11 @@
## Master
-* Added `SerializerMethodField`
+* Added `RegexField`.
+* Added `SerializerMethodField`.
* Serializer performance improvements.
-* Added `obtain_token_view` to get tokens when using `TokenAuthentication`
-* Bugfix: Django 1.5 configurable user support for `TokenAuthentication`
+* Added `obtain_token_view` to get tokens when using `TokenAuthentication`.
+* Bugfix: Django 1.5 configurable user support for `TokenAuthentication`.
## 2.1.3
diff --git a/rest_framework/fields.py b/rest_framework/fields.py
index 9dce0143..25d98645 100644
--- a/rest_framework/fields.py
+++ b/rest_framework/fields.py
@@ -1,6 +1,7 @@
import copy
import datetime
import inspect
+import re
import warnings
from io import BytesIO
@@ -802,6 +803,34 @@ class EmailField(CharField):
return result
+class RegexField(CharField):
+ type_name = 'RegexField'
+
+ def __init__(self, regex, max_length=None, min_length=None, *args, **kwargs):
+ super(RegexField, self).__init__(max_length, min_length, *args, **kwargs)
+ self.regex = regex
+
+ def _get_regex(self):
+ return self._regex
+
+ def _set_regex(self, regex):
+ if isinstance(regex, basestring):
+ regex = re.compile(regex)
+ self._regex = regex
+ if hasattr(self, '_regex_validator') and self._regex_validator in self.validators:
+ self.validators.remove(self._regex_validator)
+ self._regex_validator = validators.RegexValidator(regex=regex)
+ self.validators.append(self._regex_validator)
+
+ regex = property(_get_regex, _set_regex)
+
+ def __deepcopy__(self, memo):
+ result = copy.copy(self)
+ memo[id(self)] = result
+ result.validators = self.validators[:]
+ return result
+
+
class DateField(WritableField):
type_name = 'DateField'
diff --git a/rest_framework/tests/models.py b/rest_framework/tests/models.py
index 3704cda7..c35861c6 100644
--- a/rest_framework/tests/models.py
+++ b/rest_framework/tests/models.py
@@ -165,3 +165,8 @@ class BlankFieldModel(RESTFrameworkModel):
# Model for issue #380
class OptionalRelationModel(RESTFrameworkModel):
other = models.ForeignKey('OptionalRelationModel', blank=True, null=True)
+
+
+# Model for RegexField
+class Book(RESTFrameworkModel):
+ isbn = models.CharField(max_length=13)
diff --git a/rest_framework/tests/serializer.py b/rest_framework/tests/serializer.py
index 656bc1dd..520029ec 100644
--- a/rest_framework/tests/serializer.py
+++ b/rest_framework/tests/serializer.py
@@ -2,7 +2,7 @@ import datetime
from django.test import TestCase
from rest_framework import serializers
from rest_framework.tests.models import (ActionItem, Anchor, BasicModel,
- BlankFieldModel, BlogPost, CallableDefaultValueModel, DefaultValueModel,
+ BlankFieldModel, BlogPost, Book, CallableDefaultValueModel, DefaultValueModel,
ManyToManyModel, Person, ReadOnlyManyToManyModel)
@@ -40,6 +40,13 @@ class CommentSerializer(serializers.Serializer):
return instance
+class BookSerializer(serializers.ModelSerializer):
+ isbn = serializers.RegexField(regex=r'^[0-9]{13}$', error_messages={'invalid': 'isbn has to be exact 13 numbers'})
+
+ class Meta:
+ model = Book
+
+
class ActionItemSerializer(serializers.ModelSerializer):
class Meta:
@@ -258,6 +265,25 @@ class ValidationTests(TestCase):
self.assertEquals(serializer.errors, {'info': [u'Ensure this value has at most 12 characters (it has 13).']})
+class RegexValidationTest(TestCase):
+ def test_create_failed(self):
+ serializer = BookSerializer(data={'isbn': '1234567890'})
+ self.assertFalse(serializer.is_valid())
+ self.assertEquals(serializer.errors, {'isbn': [u'isbn has to be exact 13 numbers']})
+
+ serializer = BookSerializer(data={'isbn': '12345678901234'})
+ self.assertFalse(serializer.is_valid())
+ self.assertEquals(serializer.errors, {'isbn': [u'isbn has to be exact 13 numbers']})
+
+ serializer = BookSerializer(data={'isbn': 'abcdefghijklm'})
+ self.assertFalse(serializer.is_valid())
+ self.assertEquals(serializer.errors, {'isbn': [u'isbn has to be exact 13 numbers']})
+
+ def test_create_success(self):
+ serializer = BookSerializer(data={'isbn': '1234567890123'})
+ self.assertTrue(serializer.is_valid())
+
+
class MetadataTests(TestCase):
def test_empty(self):
serializer = CommentSerializer()