Loading django/db/models/fields/related.py +3 −3 Original line number Diff line number Diff line Loading @@ -149,7 +149,7 @@ class RelatedField(Field): return [] def _check_relation_model_exists(self): rel_is_missing = self.remote_field.model not in apps.get_models() rel_is_missing = self.remote_field.model not in self.opts.apps.get_models() rel_is_string = isinstance(self.remote_field.model, six.string_types) model_name = self.remote_field.model if rel_is_string else self.remote_field.model._meta.object_name if rel_is_missing and (rel_is_string or not self.remote_field.model._meta.swapped): Loading @@ -165,7 +165,7 @@ class RelatedField(Field): return [] def _check_referencing_to_swapped_model(self): if (self.remote_field.model not in apps.get_models() and if (self.remote_field.model not in self.opts.apps.get_models() and not isinstance(self.remote_field.model, six.string_types) and self.remote_field.model._meta.swapped): model = "%s.%s" % ( Loading Loading @@ -1206,7 +1206,7 @@ class ManyToManyField(RelatedField): errors = [] if self.remote_field.through not in apps.get_models(include_auto_created=True): if self.remote_field.through not in self.opts.apps.get_models(include_auto_created=True): # The relationship model is not installed. errors.append( checks.Error( Loading tests/invalid_models_tests/test_relative_fields.py +68 −0 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ from __future__ import unicode_literals import warnings from django.apps.registry import Apps from django.core.checks import Error, Warning as DjangoWarning from django.db import models from django.db.models.fields.related import ForeignObject Loading Loading @@ -132,6 +133,26 @@ class RelativeFieldTests(IsolatedModelsTestCase): ] self.assertEqual(errors, expected) def test_foreign_key_to_isolated_apps_model(self): """ #25723 - Referenced model registration lookup should be run against the field's model registry. """ test_apps = Apps(['invalid_models_tests']) class OtherModel(models.Model): class Meta: apps = test_apps class Model(models.Model): foreign_key = models.ForeignKey('OtherModel', models.CASCADE) class Meta: apps = test_apps field = Model._meta.get_field('foreign_key') self.assertEqual(field.check(from_model=Model), []) def test_many_to_many_to_missing_model(self): class Model(models.Model): m2m = models.ManyToManyField("Rel2") Loading @@ -149,6 +170,26 @@ class RelativeFieldTests(IsolatedModelsTestCase): ] self.assertEqual(errors, expected) def test_many_to_many_to_isolated_apps_model(self): """ #25723 - Referenced model registration lookup should be run against the field's model registry. """ test_apps = Apps(['invalid_models_tests']) class OtherModel(models.Model): class Meta: apps = test_apps class Model(models.Model): m2m = models.ManyToManyField('OtherModel') class Meta: apps = test_apps field = Model._meta.get_field('m2m') self.assertEqual(field.check(from_model=Model), []) def test_many_to_many_with_useless_options(self): class Model(models.Model): name = models.CharField(max_length=20) Loading Loading @@ -288,6 +329,33 @@ class RelativeFieldTests(IsolatedModelsTestCase): ] self.assertEqual(errors, expected) def test_many_to_many_through_isolated_apps_model(self): """ #25723 - Through model registration lookup should be run against the field's model registry. """ test_apps = Apps(['invalid_models_tests']) class GroupMember(models.Model): person = models.ForeignKey('Person', models.CASCADE) group = models.ForeignKey('Group', models.CASCADE) class Meta: apps = test_apps class Person(models.Model): class Meta: apps = test_apps class Group(models.Model): members = models.ManyToManyField('Person', through='GroupMember') class Meta: apps = test_apps field = Group._meta.get_field('members') self.assertEqual(field.check(from_model=Group), []) def test_symmetrical_self_referential_field(self): class Person(models.Model): # Implicit symmetrical=False. Loading Loading
django/db/models/fields/related.py +3 −3 Original line number Diff line number Diff line Loading @@ -149,7 +149,7 @@ class RelatedField(Field): return [] def _check_relation_model_exists(self): rel_is_missing = self.remote_field.model not in apps.get_models() rel_is_missing = self.remote_field.model not in self.opts.apps.get_models() rel_is_string = isinstance(self.remote_field.model, six.string_types) model_name = self.remote_field.model if rel_is_string else self.remote_field.model._meta.object_name if rel_is_missing and (rel_is_string or not self.remote_field.model._meta.swapped): Loading @@ -165,7 +165,7 @@ class RelatedField(Field): return [] def _check_referencing_to_swapped_model(self): if (self.remote_field.model not in apps.get_models() and if (self.remote_field.model not in self.opts.apps.get_models() and not isinstance(self.remote_field.model, six.string_types) and self.remote_field.model._meta.swapped): model = "%s.%s" % ( Loading Loading @@ -1206,7 +1206,7 @@ class ManyToManyField(RelatedField): errors = [] if self.remote_field.through not in apps.get_models(include_auto_created=True): if self.remote_field.through not in self.opts.apps.get_models(include_auto_created=True): # The relationship model is not installed. errors.append( checks.Error( Loading
tests/invalid_models_tests/test_relative_fields.py +68 −0 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ from __future__ import unicode_literals import warnings from django.apps.registry import Apps from django.core.checks import Error, Warning as DjangoWarning from django.db import models from django.db.models.fields.related import ForeignObject Loading Loading @@ -132,6 +133,26 @@ class RelativeFieldTests(IsolatedModelsTestCase): ] self.assertEqual(errors, expected) def test_foreign_key_to_isolated_apps_model(self): """ #25723 - Referenced model registration lookup should be run against the field's model registry. """ test_apps = Apps(['invalid_models_tests']) class OtherModel(models.Model): class Meta: apps = test_apps class Model(models.Model): foreign_key = models.ForeignKey('OtherModel', models.CASCADE) class Meta: apps = test_apps field = Model._meta.get_field('foreign_key') self.assertEqual(field.check(from_model=Model), []) def test_many_to_many_to_missing_model(self): class Model(models.Model): m2m = models.ManyToManyField("Rel2") Loading @@ -149,6 +170,26 @@ class RelativeFieldTests(IsolatedModelsTestCase): ] self.assertEqual(errors, expected) def test_many_to_many_to_isolated_apps_model(self): """ #25723 - Referenced model registration lookup should be run against the field's model registry. """ test_apps = Apps(['invalid_models_tests']) class OtherModel(models.Model): class Meta: apps = test_apps class Model(models.Model): m2m = models.ManyToManyField('OtherModel') class Meta: apps = test_apps field = Model._meta.get_field('m2m') self.assertEqual(field.check(from_model=Model), []) def test_many_to_many_with_useless_options(self): class Model(models.Model): name = models.CharField(max_length=20) Loading Loading @@ -288,6 +329,33 @@ class RelativeFieldTests(IsolatedModelsTestCase): ] self.assertEqual(errors, expected) def test_many_to_many_through_isolated_apps_model(self): """ #25723 - Through model registration lookup should be run against the field's model registry. """ test_apps = Apps(['invalid_models_tests']) class GroupMember(models.Model): person = models.ForeignKey('Person', models.CASCADE) group = models.ForeignKey('Group', models.CASCADE) class Meta: apps = test_apps class Person(models.Model): class Meta: apps = test_apps class Group(models.Model): members = models.ManyToManyField('Person', through='GroupMember') class Meta: apps = test_apps field = Group._meta.get_field('members') self.assertEqual(field.check(from_model=Group), []) def test_symmetrical_self_referential_field(self): class Person(models.Model): # Implicit symmetrical=False. Loading