Skip to content

Commit

Permalink
[1.9.x] Fixed #25503 -- Fixed system check crash on ForeignKey to abs…
Browse files Browse the repository at this point in the history
…tract model.

Backport of 914167a from master
  • Loading branch information
felixxm authored and timgraham committed Oct 6, 2015
1 parent d81b081 commit fbe8930
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 27 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ answer newbie questions, and generally made Django that much better:
Marian Andre <django@andre.sk>
Marijn Vriens <marijn@metronomo.cl>
Mario Gonzalez <gonzalemario@gmail.com>
Mariusz Felisiak <felisiak.mariusz@gmail.com>
Mark Biggers <biggers@utsl.com>
mark@junklight.com
Mark Lavin <markdlavin@gmail.com>
Expand Down
5 changes: 4 additions & 1 deletion django/db/models/fields/related.py
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,9 @@ def _check_unique_target(self):
except exceptions.FieldDoesNotExist:
return []

if not self.foreign_related_fields:
return []

has_unique_field = any(rel_field.unique
for rel_field in self.foreign_related_fields)
if not has_unique_field and len(self.foreign_related_fields) > 1:
Expand Down Expand Up @@ -572,7 +575,7 @@ def local_related_fields(self):

@property
def foreign_related_fields(self):
return tuple(rhs_field for lhs_field, rhs_field in self.related_fields)
return tuple(rhs_field for lhs_field, rhs_field in self.related_fields if rhs_field)

def get_local_related_value(self, instance):
return self.get_instance_value_for_fields(instance, self.local_related_fields)
Expand Down
3 changes: 3 additions & 0 deletions docs/releases/1.8.6.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,6 @@ Bugfixes

* Allowed "mode=memory" in SQLite test database name if supported
(:ticket:`12118`).

* Fixed system check crash on ``ForeignKey`` to abstract model
(:ticket:`25503`).
56 changes: 30 additions & 26 deletions tests/invalid_models_tests/test_relative_fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -386,46 +386,50 @@ class Relationship(models.Model):
self.assertEqual(errors, expected)

def test_foreign_key_to_abstract_model(self):
class Model(models.Model):
foreign_key = models.ForeignKey('AbstractModel', models.CASCADE)

class AbstractModel(models.Model):
class Meta:
abstract = True

field = Model._meta.get_field('foreign_key')
errors = field.check()
expected = [
Error(
"Field defines a relation with model 'AbstractModel', "
"which is either not installed, or is abstract.",
hint=None,
obj=field,
id='fields.E300',
),
class Model(models.Model):
rel_string_foreign_key = models.ForeignKey('AbstractModel', models.CASCADE)
rel_class_foreign_key = models.ForeignKey(AbstractModel, models.CASCADE)

fields = [
Model._meta.get_field('rel_string_foreign_key'),
Model._meta.get_field('rel_class_foreign_key'),
]
self.assertEqual(errors, expected)
expected_error = Error(
"Field defines a relation with model 'AbstractModel', "
"which is either not installed, or is abstract.",
id='fields.E300',
)
for field in fields:
expected_error.obj = field
errors = field.check()
self.assertEqual(errors, [expected_error])

def test_m2m_to_abstract_model(self):
class AbstractModel(models.Model):
class Meta:
abstract = True

class Model(models.Model):
m2m = models.ManyToManyField('AbstractModel')
rel_string_m2m = models.ManyToManyField('AbstractModel')
rel_class_m2m = models.ManyToManyField(AbstractModel)

field = Model._meta.get_field('m2m')
errors = field.check(from_model=Model)
expected = [
Error(
"Field defines a relation with model 'AbstractModel', "
"which is either not installed, or is abstract.",
hint=None,
obj=field,
id='fields.E300',
),
fields = [
Model._meta.get_field('rel_string_m2m'),
Model._meta.get_field('rel_class_m2m'),
]
self.assertEqual(errors, expected)
expected_error = Error(
"Field defines a relation with model 'AbstractModel', "
"which is either not installed, or is abstract.",
id='fields.E300',
)
for field in fields:
expected_error.obj = field
errors = field.check(from_model=Model)
self.assertEqual(errors, [expected_error])

def test_unique_m2m(self):
class Person(models.Model):
Expand Down

0 comments on commit fbe8930

Please sign in to comment.