2016-03-22 01:06:54 +00:00
|
|
|
from django.apps import apps
|
|
|
|
from django.db import models
|
|
|
|
from django.test import SimpleTestCase
|
|
|
|
from django.test.utils import isolate_apps
|
|
|
|
|
|
|
|
|
|
|
|
class ManyToManyFieldTests(SimpleTestCase):
|
|
|
|
|
2016-05-28 19:16:44 +00:00
|
|
|
@isolate_apps('model_fields')
|
|
|
|
def test_value_from_object_instance_without_pk(self):
|
|
|
|
class ManyToManyModel(models.Model):
|
|
|
|
m2m = models.ManyToManyField('self', models.CASCADE)
|
|
|
|
|
|
|
|
instance = ManyToManyModel()
|
2016-07-11 20:01:43 +00:00
|
|
|
qs = instance._meta.get_field('m2m').value_from_object(instance)
|
|
|
|
self.assertEqual(qs.model, ManyToManyModel)
|
|
|
|
self.assertEqual(list(qs), [])
|
2016-05-28 19:16:44 +00:00
|
|
|
|
2016-03-22 01:06:54 +00:00
|
|
|
def test_abstract_model_pending_operations(self):
|
|
|
|
"""
|
|
|
|
Many-to-many fields declared on abstract models should not add lazy
|
|
|
|
relations to resolve relationship declared as string (#24215).
|
|
|
|
"""
|
|
|
|
pending_ops_before = list(apps._pending_operations.items())
|
|
|
|
|
|
|
|
class AbstractManyToManyModel(models.Model):
|
|
|
|
fk = models.ForeignKey('missing.FK', models.CASCADE)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
abstract = True
|
|
|
|
|
|
|
|
self.assertIs(AbstractManyToManyModel._meta.apps, apps)
|
|
|
|
self.assertEqual(
|
|
|
|
pending_ops_before,
|
|
|
|
list(apps._pending_operations.items()),
|
|
|
|
'Pending lookup added for a many-to-many field on an abstract model'
|
|
|
|
)
|
|
|
|
|
|
|
|
@isolate_apps('model_fields', 'model_fields.tests')
|
|
|
|
def test_abstract_model_app_relative_foreign_key(self):
|
|
|
|
class AbstractReferent(models.Model):
|
2017-01-19 10:00:41 +00:00
|
|
|
reference = models.ManyToManyField('Referred', through='Through')
|
2016-03-22 01:06:54 +00:00
|
|
|
|
|
|
|
class Meta:
|
|
|
|
app_label = 'model_fields'
|
|
|
|
abstract = True
|
|
|
|
|
|
|
|
def assert_app_model_resolved(label):
|
2017-01-19 10:00:41 +00:00
|
|
|
class Referred(models.Model):
|
2016-03-22 01:06:54 +00:00
|
|
|
class Meta:
|
|
|
|
app_label = label
|
|
|
|
|
|
|
|
class Through(models.Model):
|
2017-01-19 10:00:41 +00:00
|
|
|
referred = models.ForeignKey('Referred', on_delete=models.CASCADE)
|
2016-03-22 01:06:54 +00:00
|
|
|
referent = models.ForeignKey('ConcreteReferent', on_delete=models.CASCADE)
|
|
|
|
|
|
|
|
class Meta:
|
|
|
|
app_label = label
|
|
|
|
|
|
|
|
class ConcreteReferent(AbstractReferent):
|
|
|
|
class Meta:
|
|
|
|
app_label = label
|
|
|
|
|
2017-01-19 10:00:41 +00:00
|
|
|
self.assertEqual(ConcreteReferent._meta.get_field('reference').related_model, Referred)
|
2016-03-22 01:06:54 +00:00
|
|
|
self.assertEqual(ConcreteReferent.reference.through, Through)
|
|
|
|
|
|
|
|
assert_app_model_resolved('model_fields')
|
|
|
|
assert_app_model_resolved('tests')
|