From c0da598077ea475e65741abbba6993e4677fe501 Mon Sep 17 00:00:00 2001
From: Simon Charette <charette.s@gmail.com>
Date: Fri, 4 Dec 2015 13:14:12 -0500
Subject: [PATCH] [1.9.x] Fixed #25867 -- Fixed a system check crash with
 nested ArrayFields.

Thanks to Jean Gourds for the report, Tim and Claude for the review.

Backport of 59b57e672c2f5a685804cce253d2c5314c45c5fa from master
---
 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):