Fixed #25723 -- Made related field checks lookup against their local apps.

This commit is contained in:
Simon Charette 2015-11-09 16:50:40 -05:00
parent c819780d3f
commit c550beb0cc
2 changed files with 71 additions and 3 deletions

View File

@ -147,7 +147,7 @@ class RelatedField(Field):
return [] return []
def _check_relation_model_exists(self): 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) 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 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): if rel_is_missing and (rel_is_string or not self.remote_field.model._meta.swapped):
@ -163,7 +163,7 @@ class RelatedField(Field):
return [] return []
def _check_referencing_to_swapped_model(self): 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 not isinstance(self.remote_field.model, six.string_types) and
self.remote_field.model._meta.swapped): self.remote_field.model._meta.swapped):
model = "%s.%s" % ( model = "%s.%s" % (
@ -1197,7 +1197,7 @@ class ManyToManyField(RelatedField):
errors = [] 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. # The relationship model is not installed.
errors.append( errors.append(
checks.Error( checks.Error(

View File

@ -3,6 +3,7 @@ from __future__ import unicode_literals
import warnings import warnings
from django.apps.registry import Apps
from django.core.checks import Error, Warning as DjangoWarning from django.core.checks import Error, Warning as DjangoWarning
from django.db import models from django.db import models
from django.db.models.fields.related import ForeignObject from django.db.models.fields.related import ForeignObject
@ -132,6 +133,26 @@ class RelativeFieldTests(IsolatedModelsTestCase):
] ]
self.assertEqual(errors, expected) 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): def test_many_to_many_to_missing_model(self):
class Model(models.Model): class Model(models.Model):
m2m = models.ManyToManyField("Rel2") m2m = models.ManyToManyField("Rel2")
@ -149,6 +170,26 @@ class RelativeFieldTests(IsolatedModelsTestCase):
] ]
self.assertEqual(errors, expected) 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): def test_many_to_many_with_useless_options(self):
class Model(models.Model): class Model(models.Model):
name = models.CharField(max_length=20) name = models.CharField(max_length=20)
@ -288,6 +329,33 @@ class RelativeFieldTests(IsolatedModelsTestCase):
] ]
self.assertEqual(errors, expected) 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): def test_symmetrical_self_referential_field(self):
class Person(models.Model): class Person(models.Model):
# Implicit symmetrical=False. # Implicit symmetrical=False.