Fixed #25867 -- Fixed a system check crash with nested ArrayFields.

Thanks to Jean Gourds for the report, Tim and Claude for the review.
This commit is contained in:
Simon Charette 2015-12-04 13:14:12 -05:00
parent 9c835990ea
commit 59b57e672c
3 changed files with 34 additions and 3 deletions

View File

@ -29,9 +29,17 @@ class ArrayField(Field):
self.default_validators.append(ArrayMaxLengthValidator(self.size)) self.default_validators.append(ArrayMaxLengthValidator(self.size))
super(ArrayField, self).__init__(**kwargs) super(ArrayField, self).__init__(**kwargs)
def contribute_to_class(self, cls, name, **kwargs): @property
super(ArrayField, self).contribute_to_class(cls, name, **kwargs) def model(self):
self.base_field.model = cls 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): def check(self, **kwargs):
errors = super(ArrayField, self).check(**kwargs) errors = super(ArrayField, self).check(**kwargs)

View File

@ -14,3 +14,5 @@ Bugfixes
* Fixed a regression in ``FormMixin`` causing forms to be validated twice * Fixed a regression in ``FormMixin`` causing forms to be validated twice
(:ticket:`25548`). (:ticket:`25548`).
* Fixed a system check crash with nested ``ArrayField``\s (:ticket:`25867`).

View File

@ -347,7 +347,9 @@ class TestChecks(PostgreSQLTestCase):
model = MyModel() model = MyModel()
errors = model.check() errors = model.check()
self.assertEqual(len(errors), 1) self.assertEqual(len(errors), 1)
# The inner CharField is missing a max_length.
self.assertEqual(errors[0].id, 'postgres.E001') self.assertEqual(errors[0].id, 'postgres.E001')
self.assertIn('max_length', errors[0].msg)
def test_invalid_base_fields(self): def test_invalid_base_fields(self):
test_apps = Apps(['postgres_tests']) test_apps = Apps(['postgres_tests'])
@ -363,6 +365,25 @@ class TestChecks(PostgreSQLTestCase):
self.assertEqual(len(errors), 1) self.assertEqual(len(errors), 1)
self.assertEqual(errors[0].id, 'postgres.E002') 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") @unittest.skipUnless(connection.vendor == 'postgresql', "PostgreSQL specific tests")
class TestMigrations(TransactionTestCase): class TestMigrations(TransactionTestCase):