From 59b57e672c2f5a685804cce253d2c5314c45c5fa Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Fri, 4 Dec 2015 13:14:12 -0500 Subject: [PATCH] Fixed #25867 -- Fixed a system check crash with nested ArrayFields. Thanks to Jean Gourds for the report, Tim and Claude for the review. --- django/contrib/postgres/fields/array.py | 14 +++++++++++--- docs/releases/1.9.1.txt | 2 ++ tests/postgres_tests/test_array.py | 21 +++++++++++++++++++++ 3 files changed, 34 insertions(+), 3 deletions(-) diff --git a/django/contrib/postgres/fields/array.py b/django/contrib/postgres/fields/array.py index ff37483b4f..65f28672aa 100644 --- a/django/contrib/postgres/fields/array.py +++ b/django/contrib/postgres/fields/array.py @@ -29,9 +29,17 @@ class ArrayField(Field): self.default_validators.append(ArrayMaxLengthValidator(self.size)) super(ArrayField, self).__init__(**kwargs) - def contribute_to_class(self, cls, name, **kwargs): - super(ArrayField, self).contribute_to_class(cls, name, **kwargs) - self.base_field.model = cls + @property + def model(self): + try: + return self.__dict__['model'] + except KeyError: + raise AttributeError("'%s' object has no attribute 'model'" % self.__class__.__name__) + + @model.setter + def model(self, model): + self.__dict__['model'] = model + self.base_field.model = model def check(self, **kwargs): errors = super(ArrayField, self).check(**kwargs) diff --git a/docs/releases/1.9.1.txt b/docs/releases/1.9.1.txt index e7c0bfeceb..f56c13e517 100644 --- a/docs/releases/1.9.1.txt +++ b/docs/releases/1.9.1.txt @@ -14,3 +14,5 @@ Bugfixes * Fixed a regression in ``FormMixin`` causing forms to be validated twice (:ticket:`25548`). + +* Fixed a system check crash with nested ``ArrayField``\s (:ticket:`25867`). diff --git a/tests/postgres_tests/test_array.py b/tests/postgres_tests/test_array.py index 0ff7198fc2..094a1e2235 100644 --- a/tests/postgres_tests/test_array.py +++ b/tests/postgres_tests/test_array.py @@ -347,7 +347,9 @@ class TestChecks(PostgreSQLTestCase): model = MyModel() errors = model.check() self.assertEqual(len(errors), 1) + # The inner CharField is missing a max_length. self.assertEqual(errors[0].id, 'postgres.E001') + self.assertIn('max_length', errors[0].msg) def test_invalid_base_fields(self): test_apps = Apps(['postgres_tests']) @@ -363,6 +365,25 @@ class TestChecks(PostgreSQLTestCase): self.assertEqual(len(errors), 1) self.assertEqual(errors[0].id, 'postgres.E002') + def test_nested_field_checks(self): + """ + Nested ArrayFields are permitted. + """ + test_apps = Apps(['postgres_tests']) + + class MyModel(PostgreSQLModel): + field = ArrayField(ArrayField(models.CharField())) + + class Meta: + apps = test_apps + + model = MyModel() + errors = model.check() + self.assertEqual(len(errors), 1) + # The inner CharField is missing a max_length. + self.assertEqual(errors[0].id, 'postgres.E001') + self.assertIn('max_length', errors[0].msg) + @unittest.skipUnless(connection.vendor == 'postgresql', "PostgreSQL specific tests") class TestMigrations(TransactionTestCase):