summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2016-02-15 19:28:49 +0100
committerClaude Paroz <claude@2xlibre.net>2016-02-16 21:09:16 +0100
commit205cafd01ebe0f1c72ef3772a1b3f195387f4c50 (patch)
tree52117d2195dc3afabc58134d4095787b71755f3b
parentcc7ea1905ddb4ba444b4f358c26b6bd8f1f6c93b (diff)
[1.9.x] Fixed #26215 -- Fixed RangeField/ArrayField serialization with None values
Also added tests for HStoreField and JSONField. Thanks Aleksey Bukin for the report and Tim Graham for the initial patch and the review. Backport of 928c12eb1 from master.
-rw-r--r--django/contrib/postgres/fields/array.py7
-rw-r--r--django/contrib/postgres/fields/ranges.py8
-rw-r--r--docs/releases/1.8.10.txt4
-rw-r--r--docs/releases/1.9.3.txt4
-rw-r--r--tests/postgres_tests/test_array.py6
-rw-r--r--tests/postgres_tests/test_hstore.py9
-rw-r--r--tests/postgres_tests/test_json.py6
-rw-r--r--tests/postgres_tests/test_ranges.py11
8 files changed, 44 insertions, 11 deletions
diff --git a/django/contrib/postgres/fields/array.py b/django/contrib/postgres/fields/array.py
index 65f28672aa..28e592c7be 100644
--- a/django/contrib/postgres/fields/array.py
+++ b/django/contrib/postgres/fields/array.py
@@ -107,8 +107,11 @@ class ArrayField(Field):
base_field = self.base_field
for val in vals:
- obj = AttributeSetter(base_field.attname, val)
- values.append(base_field.value_to_string(obj))
+ if val is None:
+ values.append(None)
+ else:
+ obj = AttributeSetter(base_field.attname, val)
+ values.append(base_field.value_to_string(obj))
return json.dumps(values)
def get_transform(self, name):
diff --git a/django/contrib/postgres/fields/ranges.py b/django/contrib/postgres/fields/ranges.py
index bf3f8cb9a4..5bce0743f0 100644
--- a/django/contrib/postgres/fields/ranges.py
+++ b/django/contrib/postgres/fields/ranges.py
@@ -51,8 +51,12 @@ class RangeField(models.Field):
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)
+ val = getattr(value, end)
+ if val is None:
+ result[end] = None
+ else:
+ obj = AttributeSetter(base_field.attname, val)
+ result[end] = base_field.value_to_string(obj)
return json.dumps(result)
def formfield(self, **kwargs):
diff --git a/docs/releases/1.8.10.txt b/docs/releases/1.8.10.txt
index 4eea5a3b7b..b29000eb20 100644
--- a/docs/releases/1.8.10.txt
+++ b/docs/releases/1.8.10.txt
@@ -17,3 +17,7 @@ Bugfixes
* Made ``forms.FileField`` and ``utils.translation.lazy_number()`` picklable
(:ticket:`26212`).
+
+* Fixed :class:`~django.contrib.postgres.fields.RangeField` and
+ :class:`~django.contrib.postgres.fields.ArrayField` serialization with
+ ``None`` values (:ticket:`26215`).
diff --git a/docs/releases/1.9.3.txt b/docs/releases/1.9.3.txt
index 05c6542329..af7bcf21bb 100644
--- a/docs/releases/1.9.3.txt
+++ b/docs/releases/1.9.3.txt
@@ -27,3 +27,7 @@ Bugfixes
* Made ``forms.FileField`` and ``utils.translation.lazy_number()`` picklable
(:ticket:`26212`).
+
+* Fixed :class:`~django.contrib.postgres.fields.RangeField` and
+ :class:`~django.contrib.postgres.fields.ArrayField` serialization with
+ ``None`` values (:ticket:`26215`).
diff --git a/tests/postgres_tests/test_array.py b/tests/postgres_tests/test_array.py
index 094a1e2235..fe9c477d4b 100644
--- a/tests/postgres_tests/test_array.py
+++ b/tests/postgres_tests/test_array.py
@@ -462,17 +462,17 @@ class TestMigrations(TransactionTestCase):
class TestSerialization(PostgreSQLTestCase):
test_data = (
- '[{"fields": {"field": "[\\"1\\", \\"2\\"]"}, "model": "postgres_tests.integerarraymodel", "pk": null}]'
+ '[{"fields": {"field": "[\\"1\\", \\"2\\", null]"}, "model": "postgres_tests.integerarraymodel", "pk": null}]'
)
def test_dumping(self):
- instance = IntegerArrayModel(field=[1, 2])
+ instance = IntegerArrayModel(field=[1, 2, None])
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, [1, 2])
+ self.assertEqual(instance.field, [1, 2, None])
class TestValidation(PostgreSQLTestCase):
diff --git a/tests/postgres_tests/test_hstore.py b/tests/postgres_tests/test_hstore.py
index 68c54918a1..f60f06c855 100644
--- a/tests/postgres_tests/test_hstore.py
+++ b/tests/postgres_tests/test_hstore.py
@@ -140,7 +140,8 @@ class TestQuerying(PostgreSQLTestCase):
class TestSerialization(PostgreSQLTestCase):
- test_data = '[{"fields": {"field": "{\\"a\\": \\"b\\"}"}, "model": "postgres_tests.hstoremodel", "pk": null}]'
+ test_data = ('[{"fields": {"field": "{\\"a\\": \\"b\\"}"}, '
+ '"model": "postgres_tests.hstoremodel", "pk": null}]')
def test_dumping(self):
instance = HStoreModel(field={'a': 'b'})
@@ -151,6 +152,12 @@ class TestSerialization(PostgreSQLTestCase):
instance = list(serializers.deserialize('json', self.test_data))[0].object
self.assertEqual(instance.field, {'a': 'b'})
+ def test_roundtrip_with_null(self):
+ instance = HStoreModel(field={'a': 'b', 'c': None})
+ data = serializers.serialize('json', [instance])
+ new_instance = list(serializers.deserialize('json', data))[0].object
+ self.assertEqual(instance.field, new_instance.field)
+
class TestValidation(PostgreSQLTestCase):
diff --git a/tests/postgres_tests/test_json.py b/tests/postgres_tests/test_json.py
index b4f0dd4ecf..59e5fe3fe7 100644
--- a/tests/postgres_tests/test_json.py
+++ b/tests/postgres_tests/test_json.py
@@ -213,16 +213,16 @@ class TestQuerying(TestCase):
@skipUnlessPG94
class TestSerialization(TestCase):
- test_data = '[{"fields": {"field": {"a": "b"}}, "model": "postgres_tests.jsonmodel", "pk": null}]'
+ test_data = '[{"fields": {"field": {"a": "b", "c": null}}, "model": "postgres_tests.jsonmodel", "pk": null}]'
def test_dumping(self):
- instance = JSONModel(field={'a': 'b'})
+ instance = JSONModel(field={'a': 'b', 'c': None})
data = serializers.serialize('json', [instance])
self.assertJSONEqual(data, self.test_data)
def test_loading(self):
instance = list(serializers.deserialize('json', self.test_data))[0].object
- self.assertEqual(instance.field, {'a': 'b'})
+ self.assertEqual(instance.field, {'a': 'b', 'c': None})
class TestValidation(PostgreSQLTestCase):
diff --git a/tests/postgres_tests/test_ranges.py b/tests/postgres_tests/test_ranges.py
index 5620e037b8..7478321245 100644
--- a/tests/postgres_tests/test_ranges.py
+++ b/tests/postgres_tests/test_ranges.py
@@ -323,6 +323,17 @@ class TestSerialization(TestCase):
self.assertEqual(instance.floats, NumericRange(empty=True))
self.assertEqual(instance.bigints, None)
+ def test_serialize_range_with_null(self):
+ instance = RangesModel(ints=NumericRange(None, 10))
+ data = serializers.serialize('json', [instance])
+ new_instance = list(serializers.deserialize('json', data))[0].object
+ self.assertEqual(new_instance.ints, NumericRange(None, 10))
+
+ instance = RangesModel(ints=NumericRange(10, None))
+ data = serializers.serialize('json', [instance])
+ new_instance = list(serializers.deserialize('json', data))[0].object
+ self.assertEqual(new_instance.ints, NumericRange(10, None))
+
class TestValidators(PostgreSQLTestCase):