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:14:24 +0100
commit5bce6659741ff8cf08a28f0e7fb05783c6fcf5d4 (patch)
treee2985eec32dc60b740c83612490da9c6497a2fb4
parent766fbcb1d3adfe7d3c4b575c9d6f9ac23b42350c (diff)
downloaddjango-5bce6659741ff8cf08a28f0e7fb05783c6fcf5d4.tar.gz
[1.8.x] Fixed #26215 -- Fixed RangeField/ArrayField serialization with None values
Also added tests for HStoreField. 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--tests/postgres_tests/test_array.py8
-rw-r--r--tests/postgres_tests/test_hstore.py9
-rw-r--r--tests/postgres_tests/test_ranges.py11
6 files changed, 39 insertions, 8 deletions
diff --git a/django/contrib/postgres/fields/array.py b/django/contrib/postgres/fields/array.py
index ceac798604..a2953afed0 100644
--- a/django/contrib/postgres/fields/array.py
+++ b/django/contrib/postgres/fields/array.py
@@ -95,8 +95,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 fe69b08f9a..83319b2941 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/tests/postgres_tests/test_array.py b/tests/postgres_tests/test_array.py
index b514a4329e..9146437fe7 100644
--- a/tests/postgres_tests/test_array.py
+++ b/tests/postgres_tests/test_array.py
@@ -412,16 +412,18 @@ class TestMigrations(TransactionTestCase):
class TestSerialization(TestCase):
- test_data = '[{"fields": {"field": "[\\"1\\", \\"2\\"]"}, "model": "postgres_tests.integerarraymodel", "pk": null}]'
+ test_data = (
+ '[{"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(TestCase):
diff --git a/tests/postgres_tests/test_hstore.py b/tests/postgres_tests/test_hstore.py
index f5e6f416ad..6333c82e71 100644
--- a/tests/postgres_tests/test_hstore.py
+++ b/tests/postgres_tests/test_hstore.py
@@ -130,7 +130,8 @@ class TestQuerying(TestCase):
class TestSerialization(TestCase):
- 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'})
@@ -141,6 +142,12 @@ class TestSerialization(TestCase):
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(TestCase):
diff --git a/tests/postgres_tests/test_ranges.py b/tests/postgres_tests/test_ranges.py
index feab733161..0e129c6c35 100644
--- a/tests/postgres_tests/test_ranges.py
+++ b/tests/postgres_tests/test_ranges.py
@@ -225,6 +225,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(TestCase):