summaryrefslogtreecommitdiff
path: root/tests/model_fields
diff options
context:
space:
mode:
authorMarc Tamlyn <marc.tamlyn@gmail.com>2014-07-24 13:57:24 +0100
committerMarc Tamlyn <marc.tamlyn@gmail.com>2014-12-20 18:28:29 +0000
commit57554442fe3e209c135e15dda4ea45123e579e58 (patch)
tree0ef2cb0e3048d13b82e4c7e81192df6124556a44 /tests/model_fields
parenta3d96bee36040975ded8e3bf02e33e48d06f1f16 (diff)
Fixed #2443 -- Added DurationField.
A field for storing periods of time - modeled in Python by timedelta. It is stored in the native interval data type on PostgreSQL and as a bigint of microseconds on other backends. Also includes significant changes to the internals of time related maths in expressions, including the removal of DateModifierNode. Thanks to Tim and Josh in particular for reviews.
Diffstat (limited to 'tests/model_fields')
-rw-r--r--tests/model_fields/models.py4
-rw-r--r--tests/model_fields/test_durationfield.py67
2 files changed, 71 insertions, 0 deletions
diff --git a/tests/model_fields/models.py b/tests/model_fields/models.py
index bb75208905..e9e287f04f 100644
--- a/tests/model_fields/models.py
+++ b/tests/model_fields/models.py
@@ -121,6 +121,10 @@ class DateTimeModel(models.Model):
t = models.TimeField()
+class DurationModel(models.Model):
+ field = models.DurationField()
+
+
class PrimaryKeyCharModel(models.Model):
string = models.CharField(max_length=10, primary_key=True)
diff --git a/tests/model_fields/test_durationfield.py b/tests/model_fields/test_durationfield.py
new file mode 100644
index 0000000000..fc2c22af61
--- /dev/null
+++ b/tests/model_fields/test_durationfield.py
@@ -0,0 +1,67 @@
+import datetime
+import json
+
+from django.core import exceptions, serializers
+from django.db import models
+from django.test import TestCase
+
+from .models import DurationModel
+
+
+class TestSaveLoad(TestCase):
+
+ def test_simple_roundtrip(self):
+ duration = datetime.timedelta(days=123, seconds=123, microseconds=123)
+ DurationModel.objects.create(field=duration)
+ loaded = DurationModel.objects.get()
+ self.assertEqual(loaded.field, duration)
+
+
+class TestQuerying(TestCase):
+
+ @classmethod
+ def setUpTestData(cls):
+ cls.objs = [
+ DurationModel.objects.create(field=datetime.timedelta(days=1)),
+ DurationModel.objects.create(field=datetime.timedelta(seconds=1)),
+ DurationModel.objects.create(field=datetime.timedelta(seconds=-1)),
+ ]
+
+ def test_exact(self):
+ self.assertSequenceEqual(
+ DurationModel.objects.filter(field=datetime.timedelta(days=1)),
+ [self.objs[0]]
+ )
+
+ def test_gt(self):
+ self.assertSequenceEqual(
+ DurationModel.objects.filter(field__gt=datetime.timedelta(days=0)),
+ [self.objs[0], self.objs[1]]
+ )
+
+
+class TestSerialization(TestCase):
+ test_data = '[{"fields": {"field": "1 01:00:00"}, "model": "model_fields.durationmodel", "pk": null}]'
+
+ def test_dumping(self):
+ instance = DurationModel(field=datetime.timedelta(days=1, hours=1))
+ data = serializers.serialize('json', [instance])
+ self.assertEqual(json.loads(data), json.loads(self.test_data))
+
+ def test_loading(self):
+ instance = list(serializers.deserialize('json', self.test_data))[0].object
+ self.assertEqual(instance.field, datetime.timedelta(days=1, hours=1))
+
+
+class TestValidation(TestCase):
+
+ def test_invalid_string(self):
+ field = models.DurationField()
+ with self.assertRaises(exceptions.ValidationError) as cm:
+ field.clean('not a datetime', None)
+ self.assertEqual(cm.exception.code, 'invalid')
+ self.assertEqual(
+ cm.exception.message % cm.exception.params,
+ "'not a datetime' value has an invalid format. "
+ "It must be in [DD] [HH:[MM:]]ss[.uuuuuu] format."
+ )