[1.8.x] Fixed #24937 -- Fixed serialization of Date(Time)RangeField.

Use the DjangoJSONEncoder so that datetime and date are encoded
appropriately.

Backport of 2926559cce from master
This commit is contained in:
Matthew Somerville 2015-06-05 21:56:00 +01:00 committed by Tim Graham
parent ae4613803c
commit 3ded51bcf2
3 changed files with 22 additions and 6 deletions

View File

@ -3,6 +3,7 @@ import json
from psycopg2.extras import DateRange, DateTimeTZRange, NumericRange, Range from psycopg2.extras import DateRange, DateTimeTZRange, NumericRange, Range
from django.contrib.postgres import forms, lookups from django.contrib.postgres import forms, lookups
from django.core.serializers.json import DjangoJSONEncoder
from django.db import models from django.db import models
from django.utils import six from django.utils import six
@ -41,7 +42,7 @@ class RangeField(models.Field):
"lower": value.lower, "lower": value.lower,
"upper": value.upper, "upper": value.upper,
"bounds": value._bounds, "bounds": value._bounds,
}) }, cls=DjangoJSONEncoder)
def formfield(self, **kwargs): def formfield(self, **kwargs):
kwargs.setdefault('form_class', self.form_field) kwargs.setdefault('form_class', self.form_field)

View File

@ -30,3 +30,7 @@ Bugfixes
* Fixed a regression in 1.8 by making ``gettext()`` once again return UTF-8 * Fixed a regression in 1.8 by making ``gettext()`` once again return UTF-8
bytestrings on Python 2 if the input is a bytestring (:ticket:`25720`). bytestrings on Python 2 if the input is a bytestring (:ticket:`25720`).
* Fixed serialization of
:class:`~django.contrib.postgres.fields.DateRangeField` and
:class:`~django.contrib.postgres.fields.DateTimeRangeField` (:ticket:`24937`).

View File

@ -195,24 +195,35 @@ class TestSerialization(TestCase):
test_data = ( test_data = (
'[{"fields": {"ints": "{\\"upper\\": 10, \\"lower\\": 0, ' '[{"fields": {"ints": "{\\"upper\\": 10, \\"lower\\": 0, '
'\\"bounds\\": \\"[)\\"}", "floats": "{\\"empty\\": true}", ' '\\"bounds\\": \\"[)\\"}", "floats": "{\\"empty\\": true}", '
'"bigints": null, "timestamps": null, "dates": null}, ' '"bigints": null, "timestamps": "{\\"upper\\": \\"2014-02-02T12:12:12\\", '
'\\"lower\\": \\"2014-01-01T00:00:00\\", \\"bounds\\": \\"[)\\"}", '
'"dates": "{\\"upper\\": \\"2014-02-02\\", \\"lower\\": \\"2014-01-01\\", \\"bounds\\": \\"[)\\"}" }, '
'"model": "postgres_tests.rangesmodel", "pk": null}]' '"model": "postgres_tests.rangesmodel", "pk": null}]'
) )
lower_date = datetime.date(2014, 1, 1)
upper_date = datetime.date(2014, 2, 2)
lower_dt = datetime.datetime(2014, 1, 1, 0, 0, 0)
upper_dt = datetime.datetime(2014, 2, 2, 12, 12, 12)
def test_dumping(self): def test_dumping(self):
instance = RangesModel(ints=NumericRange(0, 10), floats=NumericRange(empty=True)) instance = RangesModel(ints=NumericRange(0, 10), floats=NumericRange(empty=True),
timestamps=DateTimeTZRange(self.lower_dt, self.upper_dt),
dates=DateRange(self.lower_date, self.upper_date))
data = serializers.serialize('json', [instance]) data = serializers.serialize('json', [instance])
dumped = json.loads(data) dumped = json.loads(data)
dumped[0]['fields']['ints'] = json.loads(dumped[0]['fields']['ints']) for field in ('ints', 'dates', 'timestamps'):
dumped[0]['fields'][field] = json.loads(dumped[0]['fields'][field])
check = json.loads(self.test_data) check = json.loads(self.test_data)
check[0]['fields']['ints'] = json.loads(check[0]['fields']['ints']) for field in ('ints', 'dates', 'timestamps'):
check[0]['fields'][field] = json.loads(check[0]['fields'][field])
self.assertEqual(dumped, check) self.assertEqual(dumped, check)
def test_loading(self): def test_loading(self):
instance = list(serializers.deserialize('json', self.test_data))[0].object instance = list(serializers.deserialize('json', self.test_data))[0].object
self.assertEqual(instance.ints, NumericRange(0, 10)) self.assertEqual(instance.ints, NumericRange(0, 10))
self.assertEqual(instance.floats, NumericRange(empty=True)) self.assertEqual(instance.floats, NumericRange(empty=True))
self.assertEqual(instance.dates, None) self.assertEqual(instance.bigints, None)
class TestValidators(TestCase): class TestValidators(TestCase):