Loading django/db/models/fields/related.py +16 −15 Original line number Diff line number Diff line Loading @@ -291,7 +291,8 @@ class RelatedField(Field): if hasattr(sup, 'contribute_to_class'): sup.contribute_to_class(cls, name, virtual_only=virtual_only) if not cls._meta.abstract and self.rel.related_name: if not cls._meta.abstract: if self.rel.related_name: related_name = force_text(self.rel.related_name) % { 'class': cls.__name__.lower(), 'app_label': cls._meta.app_label.lower() Loading Loading @@ -2605,7 +2606,7 @@ class ManyToManyField(RelatedField): # Populate some necessary rel arguments so that cross-app relations # work correctly. if isinstance(self.rel.through, six.string_types): if not cls._meta.abstract and isinstance(self.rel.through, six.string_types): def resolve_through_model(field, model, cls): field.rel.through = model add_lazy_relation(cls, self, self.rel.through, resolve_through_model) Loading tests/model_fields/models.py +11 −0 Original line number Diff line number Diff line Loading @@ -367,3 +367,14 @@ class NullableUUIDModel(models.Model): class PrimaryKeyUUIDModel(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4) ############################################################################### # See ticket #24215. class AbstractForeignFieldsModel(models.Model): fk = models.ForeignKey('missing.FK') m2m = models.ManyToManyField('missing.M2M', through='missing.Through') class Meta: abstract = True tests/model_fields/tests.py +39 −5 Original line number Diff line number Diff line Loading @@ -21,11 +21,12 @@ from django.utils import six from django.utils.functional import lazy from .models import ( Bar, BigD, BigIntegerModel, BigS, BooleanModel, DataModel, DateTimeModel, Document, FksToBooleans, FkToChar, FloatModel, Foo, GenericIPAddress, IntegerModel, NullBooleanModel, PositiveIntegerModel, PositiveSmallIntegerModel, Post, PrimaryKeyCharModel, RenamedField, SmallIntegerModel, VerboseNameField, Whiz, WhizIter, WhizIterEmpty, AbstractForeignFieldsModel, Bar, BigD, BigIntegerModel, BigS, BooleanModel, DataModel, DateTimeModel, Document, FksToBooleans, FkToChar, FloatModel, Foo, GenericIPAddress, IntegerModel, NullBooleanModel, PositiveIntegerModel, PositiveSmallIntegerModel, Post, PrimaryKeyCharModel, RenamedField, SmallIntegerModel, VerboseNameField, Whiz, WhizIter, WhizIterEmpty, ) Loading Loading @@ -201,6 +202,39 @@ class ForeignKeyTests(test.TestCase): rel_name = Bar._meta.get_field('a').rel.related_name self.assertIsInstance(rel_name, six.text_type) def test_abstract_model_pending_lookups(self): """ Foreign key fields declared on abstract models should not add lazy relations to resolve relationship declared as string. refs #24215 """ opts = AbstractForeignFieldsModel._meta to_key = ('missing', 'FK') fk_lookup = (AbstractForeignFieldsModel, opts.get_field('fk')) self.assertFalse( any(lookup[0:2] == fk_lookup for lookup in opts.apps._pending_lookups.get(to_key, [])), 'Pending lookup added for the abstract model foreign key `to` parameter' ) class ManyToManyFieldTests(test.TestCase): def test_abstract_model_pending_lookups(self): """ Many-to-many fields declared on abstract models should not add lazy relations to resolve relationship declared as string. refs #24215 """ opts = AbstractForeignFieldsModel._meta to_key = ('missing', 'M2M') fk_lookup = (AbstractForeignFieldsModel, opts.get_field('m2m')) self.assertFalse( any(lookup[0:2] == fk_lookup for lookup in opts.apps._pending_lookups.get(to_key, [])), 'Pending lookup added for the abstract model many-to-many `to` parameter.' ) through_key = ('missing', 'Through') self.assertFalse( any(lookup[0:2] == fk_lookup for lookup in opts.apps._pending_lookups.get(through_key, [])), 'Pending lookup added for the abstract model many-to-many `through` parameter.' ) class DateTimeFieldTests(unittest.TestCase): def test_datetimefield_to_python_usecs(self): Loading Loading
django/db/models/fields/related.py +16 −15 Original line number Diff line number Diff line Loading @@ -291,7 +291,8 @@ class RelatedField(Field): if hasattr(sup, 'contribute_to_class'): sup.contribute_to_class(cls, name, virtual_only=virtual_only) if not cls._meta.abstract and self.rel.related_name: if not cls._meta.abstract: if self.rel.related_name: related_name = force_text(self.rel.related_name) % { 'class': cls.__name__.lower(), 'app_label': cls._meta.app_label.lower() Loading Loading @@ -2605,7 +2606,7 @@ class ManyToManyField(RelatedField): # Populate some necessary rel arguments so that cross-app relations # work correctly. if isinstance(self.rel.through, six.string_types): if not cls._meta.abstract and isinstance(self.rel.through, six.string_types): def resolve_through_model(field, model, cls): field.rel.through = model add_lazy_relation(cls, self, self.rel.through, resolve_through_model) Loading
tests/model_fields/models.py +11 −0 Original line number Diff line number Diff line Loading @@ -367,3 +367,14 @@ class NullableUUIDModel(models.Model): class PrimaryKeyUUIDModel(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4) ############################################################################### # See ticket #24215. class AbstractForeignFieldsModel(models.Model): fk = models.ForeignKey('missing.FK') m2m = models.ManyToManyField('missing.M2M', through='missing.Through') class Meta: abstract = True
tests/model_fields/tests.py +39 −5 Original line number Diff line number Diff line Loading @@ -21,11 +21,12 @@ from django.utils import six from django.utils.functional import lazy from .models import ( Bar, BigD, BigIntegerModel, BigS, BooleanModel, DataModel, DateTimeModel, Document, FksToBooleans, FkToChar, FloatModel, Foo, GenericIPAddress, IntegerModel, NullBooleanModel, PositiveIntegerModel, PositiveSmallIntegerModel, Post, PrimaryKeyCharModel, RenamedField, SmallIntegerModel, VerboseNameField, Whiz, WhizIter, WhizIterEmpty, AbstractForeignFieldsModel, Bar, BigD, BigIntegerModel, BigS, BooleanModel, DataModel, DateTimeModel, Document, FksToBooleans, FkToChar, FloatModel, Foo, GenericIPAddress, IntegerModel, NullBooleanModel, PositiveIntegerModel, PositiveSmallIntegerModel, Post, PrimaryKeyCharModel, RenamedField, SmallIntegerModel, VerboseNameField, Whiz, WhizIter, WhizIterEmpty, ) Loading Loading @@ -201,6 +202,39 @@ class ForeignKeyTests(test.TestCase): rel_name = Bar._meta.get_field('a').rel.related_name self.assertIsInstance(rel_name, six.text_type) def test_abstract_model_pending_lookups(self): """ Foreign key fields declared on abstract models should not add lazy relations to resolve relationship declared as string. refs #24215 """ opts = AbstractForeignFieldsModel._meta to_key = ('missing', 'FK') fk_lookup = (AbstractForeignFieldsModel, opts.get_field('fk')) self.assertFalse( any(lookup[0:2] == fk_lookup for lookup in opts.apps._pending_lookups.get(to_key, [])), 'Pending lookup added for the abstract model foreign key `to` parameter' ) class ManyToManyFieldTests(test.TestCase): def test_abstract_model_pending_lookups(self): """ Many-to-many fields declared on abstract models should not add lazy relations to resolve relationship declared as string. refs #24215 """ opts = AbstractForeignFieldsModel._meta to_key = ('missing', 'M2M') fk_lookup = (AbstractForeignFieldsModel, opts.get_field('m2m')) self.assertFalse( any(lookup[0:2] == fk_lookup for lookup in opts.apps._pending_lookups.get(to_key, [])), 'Pending lookup added for the abstract model many-to-many `to` parameter.' ) through_key = ('missing', 'Through') self.assertFalse( any(lookup[0:2] == fk_lookup for lookup in opts.apps._pending_lookups.get(through_key, [])), 'Pending lookup added for the abstract model many-to-many `through` parameter.' ) class DateTimeFieldTests(unittest.TestCase): def test_datetimefield_to_python_usecs(self): Loading