mirror of
https://github.com/django/django.git
synced 2025-07-19 09:09:13 +00:00
[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.
This commit is contained in:
parent
cc7ea1905d
commit
205cafd01e
@ -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):
|
||||
|
@ -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`).
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
||||
|
@ -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):
|
||||
|
@ -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):
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user