mirror of https://github.com/django/django.git
Refs #24215 -- Prevented pending lookup pollution by abstract models.
This commit is contained in:
parent
e519ee1d35
commit
9239f1dda7
|
@ -291,20 +291,21 @@ 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:
|
||||
related_name = force_text(self.rel.related_name) % {
|
||||
'class': cls.__name__.lower(),
|
||||
'app_label': cls._meta.app_label.lower()
|
||||
}
|
||||
self.rel.related_name = related_name
|
||||
other = self.rel.to
|
||||
if isinstance(other, six.string_types) or other._meta.pk is None:
|
||||
def resolve_related_class(field, model, cls):
|
||||
field.rel.to = model
|
||||
field.do_related_class(model, cls)
|
||||
add_lazy_relation(cls, self, other, resolve_related_class)
|
||||
else:
|
||||
self.do_related_class(other, cls)
|
||||
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()
|
||||
}
|
||||
self.rel.related_name = related_name
|
||||
other = self.rel.to
|
||||
if isinstance(other, six.string_types) or other._meta.pk is None:
|
||||
def resolve_related_class(field, model, cls):
|
||||
field.rel.to = model
|
||||
field.do_related_class(model, cls)
|
||||
add_lazy_relation(cls, self, other, resolve_related_class)
|
||||
else:
|
||||
self.do_related_class(other, cls)
|
||||
|
||||
@property
|
||||
def swappable_setting(self):
|
||||
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
)
|
||||
|
||||
|
||||
|
@ -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…
Reference in New Issue