aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/api-guide/fields.md8
-rw-r--r--rest_framework/compat.py2
-rw-r--r--rest_framework/fields.py28
-rw-r--r--rest_framework/serializers.py1
-rw-r--r--rest_framework/tests/fields.py48
5 files changed, 84 insertions, 3 deletions
diff --git a/docs/api-guide/fields.md b/docs/api-guide/fields.md
index 3f8a36e2..8c28273b 100644
--- a/docs/api-guide/fields.md
+++ b/docs/api-guide/fields.md
@@ -199,10 +199,16 @@ If you want to override this behavior, you'll need to declare the `DateTimeField
class CommentSerializer(serializers.ModelSerializer):
created = serializers.DateTimeField()
-
+
class Meta:
model = Comment
+## TimeField
+
+A time representation.
+
+Corresponds to `django.db.models.fields.TimeField`
+
## IntegerField
An integer representation.
diff --git a/rest_framework/compat.py b/rest_framework/compat.py
index 9636b9c1..3fd865f8 100644
--- a/rest_framework/compat.py
+++ b/rest_framework/compat.py
@@ -349,7 +349,7 @@ except ImportError:
# dateparse is ALSO new in Django 1.4
try:
- from django.utils.dateparse import parse_date, parse_datetime
+ from django.utils.dateparse import parse_date, parse_datetime, parse_time
except ImportError:
import datetime
import re
diff --git a/rest_framework/fields.py b/rest_framework/fields.py
index 327008fb..236e0f1e 100644
--- a/rest_framework/fields.py
+++ b/rest_framework/fields.py
@@ -18,6 +18,7 @@ from rest_framework.compat import timezone
from rest_framework.compat import BytesIO
from rest_framework.compat import six
from rest_framework.compat import smart_text
+from rest_framework.compat import parse_time
def is_simple_callable(obj):
@@ -531,6 +532,33 @@ class DateTimeField(WritableField):
raise ValidationError(msg)
+class TimeField(WritableField):
+ type_name = 'TimeField'
+ widget = widgets.TimeInput
+ form_field_class = forms.TimeField
+
+ default_error_messages = {
+ 'invalid': _("'%s' value has an invalid format. It must be a valid "
+ "time in the HH:MM[:ss[.uuuuuu]] format."),
+ }
+ empty = None
+
+ def from_native(self, value):
+ if value in validators.EMPTY_VALUES:
+ return None
+
+ if isinstance(value, datetime.time):
+ return value
+
+ try:
+ parsed = parse_time(value)
+ assert parsed is not None
+ return parsed
+ except ValueError:
+ msg = self.error_messages['invalid'] % value
+ raise ValidationError(msg)
+
+
class IntegerField(WritableField):
type_name = 'IntegerField'
form_field_class = forms.IntegerField
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 5d3475d4..b0372ab8 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -517,6 +517,7 @@ class ModelSerializer(Serializer):
models.PositiveSmallIntegerField: IntegerField,
models.DateTimeField: DateTimeField,
models.DateField: DateField,
+ models.TimeField: TimeField,
models.EmailField: EmailField,
models.CharField: CharField,
models.URLField: URLField,
diff --git a/rest_framework/tests/fields.py b/rest_framework/tests/fields.py
index b7587bf1..34f61678 100644
--- a/rest_framework/tests/fields.py
+++ b/rest_framework/tests/fields.py
@@ -2,8 +2,10 @@
General serializer field tests.
"""
from __future__ import unicode_literals
+import datetime
from django.db import models
from django.test import TestCase
+from django.core import validators
from rest_framework import serializers
@@ -26,7 +28,16 @@ class CharPrimaryKeyModelSerializer(serializers.ModelSerializer):
model = CharPrimaryKeyModel
-class ReadOnlyFieldTests(TestCase):
+class TimeFieldModel(models.Model):
+ clock = models.TimeField()
+
+
+class TimeFieldModelSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = TimeFieldModel
+
+
+class BasicFieldTests(TestCase):
def test_auto_now_fields_read_only(self):
"""
auto_now and auto_now_add fields should be read_only by default.
@@ -47,3 +58,38 @@ class ReadOnlyFieldTests(TestCase):
"""
serializer = CharPrimaryKeyModelSerializer()
self.assertEquals(serializer.fields['id'].read_only, False)
+
+ def test_TimeField_from_native(self):
+ f = serializers.TimeField()
+ result = f.from_native('12:34:56.987654')
+
+ self.assertEqual(datetime.time(12, 34, 56, 987654), result)
+
+ def test_TimeField_from_native_datetime_time(self):
+ """
+ Make sure from_native() accepts a datetime.time instance.
+ """
+ f = serializers.TimeField()
+ result = f.from_native(datetime.time(12, 34, 56))
+ self.assertEqual(result, datetime.time(12, 34, 56))
+
+ def test_TimeField_from_native_empty(self):
+ f = serializers.TimeField()
+ result = f.from_native('')
+ self.assertEqual(result, None)
+
+ def test_TimeField_from_native_invalid_time(self):
+ f = serializers.TimeField()
+
+ try:
+ f.from_native('12:69:12')
+ except validators.ValidationError as e:
+ self.assertEqual(e.messages, ["'12:69:12' value has an invalid "
+ "format. It must be a valid time "
+ "in the HH:MM[:ss[.uuuuuu]] format."])
+ else:
+ self.fail("ValidationError was not properly raised")
+
+ def test_TimeFieldModelSerializer(self):
+ serializer = TimeFieldModelSerializer()
+ self.assertTrue(isinstance(serializer.fields['clock'], serializers.TimeField))