Loading django/contrib/postgres/fields/array.py +2 −5 Original line number Diff line number Diff line Loading @@ -8,12 +8,9 @@ from django.db.models import Field, IntegerField, Transform from django.utils import six from django.utils.translation import string_concat, ugettext_lazy as _ __all__ = ['ArrayField'] from .utils import AttributeSetter class AttributeSetter(object): def __init__(self, name, value): setattr(self, name, value) __all__ = ['ArrayField'] class ArrayField(Field): Loading django/contrib/postgres/fields/ranges.py +18 −6 Original line number Diff line number Diff line Loading @@ -6,6 +6,8 @@ from django.contrib.postgres import forms, lookups from django.db import models from django.utils import six from .utils import AttributeSetter __all__ = [ 'RangeField', 'IntegerRangeField', 'BigIntegerRangeField', 'FloatRangeField', 'DateTimeRangeField', 'DateRangeField', Loading @@ -26,22 +28,32 @@ class RangeField(models.Field): def to_python(self, value): if isinstance(value, six.string_types): value = self.range_type(**json.loads(value)) # Assume we're deserializing vals = json.loads(value) for end in ('lower', 'upper'): if end in vals: vals[end] = self.base_field.to_python(vals[end]) value = self.range_type(**vals) elif isinstance(value, (list, tuple)): value = self.range_type(value[0], value[1]) return value def set_attributes_from_name(self, name): super(RangeField, self).set_attributes_from_name(name) self.base_field.set_attributes_from_name(name) def value_to_string(self, obj): value = self._get_val_from_obj(obj) if value is None: return None if value.isempty: return json.dumps({"empty": True}) return json.dumps({ "lower": value.lower, "upper": value.upper, "bounds": value._bounds, }) base_field = self.base_field result = {"bounds": value._bounds} for end in ('lower', 'upper'): obj = AttributeSetter(base_field.attname, getattr(value, end)) result[end] = base_field.value_to_string(obj) return json.dumps(result) def formfield(self, **kwargs): kwargs.setdefault('form_class', self.form_field) Loading django/contrib/postgres/fields/utils.py 0 → 100644 +3 −0 Original line number Diff line number Diff line class AttributeSetter(object): def __init__(self, name, value): setattr(self, name, value) docs/releases/1.9.txt +4 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,10 @@ Minor features * Added :class:`~django.contrib.postgres.fields.JSONField`. * Added :doc:`/ref/contrib/postgres/aggregates`. * Fixed serialization of :class:`~django.contrib.postgres.fields.DateRangeField` and :class:`~django.contrib.postgres.fields.DateTimeRangeField`. :mod:`django.contrib.redirects` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Loading tests/postgres_tests/test_ranges.py +17 −6 Original line number Diff line number Diff line Loading @@ -291,26 +291,37 @@ class TestQueringWithRanges(TestCase): @skipUnlessPG92 class TestSerialization(TestCase): test_data = ( '[{"fields": {"ints": "{\\"upper\\": 10, \\"lower\\": 0, ' '[{"fields": {"ints": "{\\"upper\\": \\"10\\", \\"lower\\": \\"0\\", ' '\\"bounds\\": \\"[)\\"}", "floats": "{\\"empty\\": true}", ' '"bigints": null, "timestamps": null, "dates": null}, ' '"bigints": null, "timestamps": "{\\"upper\\": \\"2014-02-02T12:12:12+00:00\\", ' '\\"lower\\": \\"2014-01-01T00:00:00+00:00\\", \\"bounds\\": \\"[)\\"}", ' '"dates": "{\\"upper\\": \\"2014-02-02\\", \\"lower\\": \\"2014-01-01\\", \\"bounds\\": \\"[)\\"}" }, ' '"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, tzinfo=timezone.utc) upper_dt = datetime.datetime(2014, 2, 2, 12, 12, 12, tzinfo=timezone.utc) 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]) 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[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) def test_loading(self): instance = list(serializers.deserialize('json', self.test_data))[0].object self.assertEqual(instance.ints, NumericRange(0, 10)) self.assertEqual(instance.floats, NumericRange(empty=True)) self.assertEqual(instance.dates, None) self.assertEqual(instance.bigints, None) class TestValidators(PostgreSQLTestCase): Loading Loading
django/contrib/postgres/fields/array.py +2 −5 Original line number Diff line number Diff line Loading @@ -8,12 +8,9 @@ from django.db.models import Field, IntegerField, Transform from django.utils import six from django.utils.translation import string_concat, ugettext_lazy as _ __all__ = ['ArrayField'] from .utils import AttributeSetter class AttributeSetter(object): def __init__(self, name, value): setattr(self, name, value) __all__ = ['ArrayField'] class ArrayField(Field): Loading
django/contrib/postgres/fields/ranges.py +18 −6 Original line number Diff line number Diff line Loading @@ -6,6 +6,8 @@ from django.contrib.postgres import forms, lookups from django.db import models from django.utils import six from .utils import AttributeSetter __all__ = [ 'RangeField', 'IntegerRangeField', 'BigIntegerRangeField', 'FloatRangeField', 'DateTimeRangeField', 'DateRangeField', Loading @@ -26,22 +28,32 @@ class RangeField(models.Field): def to_python(self, value): if isinstance(value, six.string_types): value = self.range_type(**json.loads(value)) # Assume we're deserializing vals = json.loads(value) for end in ('lower', 'upper'): if end in vals: vals[end] = self.base_field.to_python(vals[end]) value = self.range_type(**vals) elif isinstance(value, (list, tuple)): value = self.range_type(value[0], value[1]) return value def set_attributes_from_name(self, name): super(RangeField, self).set_attributes_from_name(name) self.base_field.set_attributes_from_name(name) def value_to_string(self, obj): value = self._get_val_from_obj(obj) if value is None: return None if value.isempty: return json.dumps({"empty": True}) return json.dumps({ "lower": value.lower, "upper": value.upper, "bounds": value._bounds, }) base_field = self.base_field result = {"bounds": value._bounds} for end in ('lower', 'upper'): obj = AttributeSetter(base_field.attname, getattr(value, end)) result[end] = base_field.value_to_string(obj) return json.dumps(result) def formfield(self, **kwargs): kwargs.setdefault('form_class', self.form_field) Loading
django/contrib/postgres/fields/utils.py 0 → 100644 +3 −0 Original line number Diff line number Diff line class AttributeSetter(object): def __init__(self, name, value): setattr(self, name, value)
docs/releases/1.9.txt +4 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,10 @@ Minor features * Added :class:`~django.contrib.postgres.fields.JSONField`. * Added :doc:`/ref/contrib/postgres/aggregates`. * Fixed serialization of :class:`~django.contrib.postgres.fields.DateRangeField` and :class:`~django.contrib.postgres.fields.DateTimeRangeField`. :mod:`django.contrib.redirects` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Loading
tests/postgres_tests/test_ranges.py +17 −6 Original line number Diff line number Diff line Loading @@ -291,26 +291,37 @@ class TestQueringWithRanges(TestCase): @skipUnlessPG92 class TestSerialization(TestCase): test_data = ( '[{"fields": {"ints": "{\\"upper\\": 10, \\"lower\\": 0, ' '[{"fields": {"ints": "{\\"upper\\": \\"10\\", \\"lower\\": \\"0\\", ' '\\"bounds\\": \\"[)\\"}", "floats": "{\\"empty\\": true}", ' '"bigints": null, "timestamps": null, "dates": null}, ' '"bigints": null, "timestamps": "{\\"upper\\": \\"2014-02-02T12:12:12+00:00\\", ' '\\"lower\\": \\"2014-01-01T00:00:00+00:00\\", \\"bounds\\": \\"[)\\"}", ' '"dates": "{\\"upper\\": \\"2014-02-02\\", \\"lower\\": \\"2014-01-01\\", \\"bounds\\": \\"[)\\"}" }, ' '"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, tzinfo=timezone.utc) upper_dt = datetime.datetime(2014, 2, 2, 12, 12, 12, tzinfo=timezone.utc) 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]) 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[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) def test_loading(self): instance = list(serializers.deserialize('json', self.test_data))[0].object self.assertEqual(instance.ints, NumericRange(0, 10)) self.assertEqual(instance.floats, NumericRange(empty=True)) self.assertEqual(instance.dates, None) self.assertEqual(instance.bigints, None) class TestValidators(PostgreSQLTestCase): Loading