From 3af695eda24b874486ee8be7e0d729761b3bdc71 Mon Sep 17 00:00:00 2001 From: vinay karanam Date: Fri, 27 Jul 2018 15:35:54 +0000 Subject: [PATCH] Fixed #28291, #24726 -- Fixed ArrayField with JSONField and RangeFields. --- AUTHORS | 1 + django/contrib/postgres/fields/array.py | 3 +++ .../migrations/0002_create_test_models.py | 3 +++ tests/postgres_tests/models.py | 3 +++ tests/postgres_tests/test_array.py | 13 +++++++++++++ 5 files changed, 23 insertions(+) diff --git a/AUTHORS b/AUTHORS index 89b6540f69..79abc88a73 100644 --- a/AUTHORS +++ b/AUTHORS @@ -851,6 +851,7 @@ answer newbie questions, and generally made Django that much better: viestards.lists@gmail.com Viktor Danyliuk Ville Säävuori + Vinay Karanam Vinay Sajip Vincent Foley Vitaly Babiy diff --git a/django/contrib/postgres/fields/array.py b/django/contrib/postgres/fields/array.py index ab667acd5b..a6079466af 100644 --- a/django/contrib/postgres/fields/array.py +++ b/django/contrib/postgres/fields/array.py @@ -84,6 +84,9 @@ class ArrayField(CheckFieldDefaultMixin, Field): size = self.size or '' return '%s[%s]' % (self.base_field.db_type(connection), size) + def get_placeholder(self, value, compiler, connection): + return '%s::{}'.format(self.db_type(connection)) + def get_db_prep_value(self, value, connection, prepared=False): if isinstance(value, (list, tuple)): return [self.base_field.get_db_prep_value(i, connection, prepared=False) for i in value] diff --git a/tests/postgres_tests/migrations/0002_create_test_models.py b/tests/postgres_tests/migrations/0002_create_test_models.py index 57465612b5..9f4417b58d 100644 --- a/tests/postgres_tests/migrations/0002_create_test_models.py +++ b/tests/postgres_tests/migrations/0002_create_test_models.py @@ -60,6 +60,9 @@ class Migration(migrations.Migration): ('uuids', ArrayField(models.UUIDField(), size=None)), ('decimals', ArrayField(models.DecimalField(max_digits=5, decimal_places=2), size=None)), ('tags', ArrayField(TagField(), blank=True, null=True, size=None)), + ('json', ArrayField(JSONField(default={}), default=[])), + ('int_ranges', ArrayField(IntegerRangeField(), null=True, blank=True)), + ('bigint_ranges', ArrayField(BigIntegerRangeField(), null=True, blank=True)), ], options={ 'required_db_vendor': 'postgresql', diff --git a/tests/postgres_tests/models.py b/tests/postgres_tests/models.py index d5865818e7..cd1646a3e6 100644 --- a/tests/postgres_tests/models.py +++ b/tests/postgres_tests/models.py @@ -67,6 +67,9 @@ class OtherTypesArrayModel(PostgreSQLModel): uuids = ArrayField(models.UUIDField()) decimals = ArrayField(models.DecimalField(max_digits=5, decimal_places=2)) tags = ArrayField(TagField(), blank=True, null=True) + json = ArrayField(JSONField(default=dict), default=list) + int_ranges = ArrayField(IntegerRangeField(), blank=True, null=True) + bigint_ranges = ArrayField(BigIntegerRangeField(), blank=True, null=True) class HStoreModel(PostgreSQLModel): diff --git a/tests/postgres_tests/test_array.py b/tests/postgres_tests/test_array.py index d0e10dcb31..25fbc230bb 100644 --- a/tests/postgres_tests/test_array.py +++ b/tests/postgres_tests/test_array.py @@ -24,6 +24,7 @@ try: from django.contrib.postgres.forms import ( SimpleArrayField, SplitArrayField, SplitArrayWidget, ) + from psycopg2.extras import NumericRange except ImportError: pass @@ -96,6 +97,12 @@ class TestSaveLoad(PostgreSQLTestCase): uuids=[uuid.uuid4()], decimals=[decimal.Decimal(1.25), 1.75], tags=[Tag(1), Tag(2), Tag(3)], + json=[{'a': 1}, {'b': 2}], + int_ranges=[NumericRange(10, 20), NumericRange(30, 40)], + bigint_ranges=[ + NumericRange(7000000000, 10000000000), + NumericRange(50000000000, 70000000000), + ] ) instance.save() loaded = OtherTypesArrayModel.objects.get() @@ -103,6 +110,9 @@ class TestSaveLoad(PostgreSQLTestCase): self.assertEqual(instance.uuids, loaded.uuids) self.assertEqual(instance.decimals, loaded.decimals) self.assertEqual(instance.tags, loaded.tags) + self.assertEqual(instance.json, loaded.json) + self.assertEqual(instance.int_ranges, loaded.int_ranges) + self.assertEqual(instance.bigint_ranges, loaded.bigint_ranges) def test_null_from_db_value_handling(self): instance = OtherTypesArrayModel.objects.create( @@ -113,6 +123,9 @@ class TestSaveLoad(PostgreSQLTestCase): ) instance.refresh_from_db() self.assertIsNone(instance.tags) + self.assertEqual(instance.json, []) + self.assertIsNone(instance.int_ranges) + self.assertIsNone(instance.bigint_ranges) def test_model_set_on_base_field(self): instance = IntegerArrayModel()