Kaydet (Commit) 928c12eb authored tarafından Claude Paroz's avatar Claude Paroz

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.
üst b09b71bf
......@@ -106,8 +106,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):
......
......@@ -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):
......
......@@ -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`).
......@@ -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`).
......@@ -448,17 +448,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):
......
......@@ -165,7 +165,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'})
......@@ -176,6 +177,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):
......
......@@ -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):
......
......@@ -309,6 +309,17 @@ class TestSerialization(PostgreSQLTestCase):
self.assertEqual(instance.dates, DateRange(self.lower_date, self.upper_date))
self.assertEqual(instance.timestamps, DateTimeTZRange(self.lower_dt, self.upper_dt))
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):
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment