From c550beb0ccc8855fde7ff50ada530f7ceff1a595 Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Mon, 9 Nov 2015 16:50:40 -0500 Subject: [PATCH] Fixed #25723 -- Made related field checks lookup against their local apps. --- django/db/models/fields/related.py | 6 +- .../test_relative_fields.py | 68 +++++++++++++++++++ 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/django/db/models/fields/related.py b/django/db/models/fields/related.py index 1fcd2dd7219..fdf072d2dd1 100644 --- a/django/db/models/fields/related.py +++ b/django/db/models/fields/related.py @@ -147,7 +147,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): @@ -163,7 +163,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" % ( @@ -1197,7 +1197,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( diff --git a/tests/invalid_models_tests/test_relative_fields.py b/tests/invalid_models_tests/test_relative_fields.py index bfdd2b7d7af..3ec9af2cb01 100644 --- a/tests/invalid_models_tests/test_relative_fields.py +++ b/tests/invalid_models_tests/test_relative_fields.py @@ -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 @@ -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") @@ -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) @@ -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.