Fixed #20883 -- Made model inheritance find parent links in abstract parents
This commit is contained in:
parent
dcdc579d16
commit
163a34ce4b
|
@ -184,10 +184,21 @@ class ModelBase(type):
|
|||
else:
|
||||
new_class._meta.concrete_model = new_class
|
||||
|
||||
# Do the appropriate setup for any model parents.
|
||||
o2o_map = dict([(f.rel.to, f) for f in new_class._meta.local_fields
|
||||
if isinstance(f, OneToOneField)])
|
||||
# Collect the parent links for multi-table inheritance.
|
||||
parent_links = {}
|
||||
for base in reversed([new_class] + parents):
|
||||
# Conceptually equivalent to `if base is Model`.
|
||||
if not hasattr(base, '_meta'):
|
||||
continue
|
||||
# Skip concrete parent classes.
|
||||
if base != new_class and not base._meta.abstract:
|
||||
continue
|
||||
# Locate OneToOneField instances.
|
||||
for field in base._meta.local_fields:
|
||||
if isinstance(field, OneToOneField):
|
||||
parent_links[field.rel.to] = field
|
||||
|
||||
# Do the appropriate setup for any model parents.
|
||||
for base in parents:
|
||||
original_base = base
|
||||
if not hasattr(base, '_meta'):
|
||||
|
@ -208,8 +219,8 @@ class ModelBase(type):
|
|||
if not base._meta.abstract:
|
||||
# Concrete classes...
|
||||
base = base._meta.concrete_model
|
||||
if base in o2o_map:
|
||||
field = o2o_map[base]
|
||||
if base in parent_links:
|
||||
field = parent_links[base]
|
||||
elif not is_proxy:
|
||||
attr_name = '%s_ptr' % base._meta.model_name
|
||||
field = OneToOneField(base, name=attr_name,
|
||||
|
|
|
@ -142,6 +142,9 @@ Minor features
|
|||
the file system permissions of directories created during file upload, like
|
||||
:setting:`FILE_UPLOAD_PERMISSIONS` does for the files themselves.
|
||||
|
||||
* Explicit :class:`~django.db.models.OneToOneField` for
|
||||
:ref:`multi-table-inheritance` are now discovered in abstract classes.
|
||||
|
||||
Backwards incompatible changes in 1.7
|
||||
=====================================
|
||||
|
||||
|
|
|
@ -50,6 +50,19 @@ class ParkingLot3(Place):
|
|||
primary_key = models.AutoField(primary_key=True)
|
||||
parent = models.OneToOneField(Place, parent_link=True)
|
||||
|
||||
class ParkingLot4(models.Model):
|
||||
# Test parent_link connector can be discovered in abstract classes.
|
||||
parent = models.OneToOneField(Place, parent_link=True)
|
||||
|
||||
class Meta:
|
||||
abstract = True
|
||||
|
||||
class ParkingLot4A(ParkingLot4, Place):
|
||||
pass
|
||||
|
||||
class ParkingLot4B(Place, ParkingLot4):
|
||||
pass
|
||||
|
||||
class Supplier(models.Model):
|
||||
restaurant = models.ForeignKey(Restaurant)
|
||||
|
||||
|
|
|
@ -14,7 +14,8 @@ from .models import (Place, Restaurant, ItalianRestaurant, ParkingLot,
|
|||
ParkingLot2, ParkingLot3, Supplier, Wholesaler, Child, SelfRefParent,
|
||||
SelfRefChild, ArticleWithAuthor, M2MChild, QualityControl, DerivedM,
|
||||
Person, BirthdayParty, BachelorParty, MessyBachelorParty,
|
||||
InternalCertificationAudit, BusStation, TrainStation, User, Profile)
|
||||
InternalCertificationAudit, BusStation, TrainStation, User, Profile,
|
||||
ParkingLot4A, ParkingLot4B)
|
||||
|
||||
|
||||
class ModelInheritanceTest(TestCase):
|
||||
|
@ -311,6 +312,19 @@ class ModelInheritanceTest(TestCase):
|
|||
ParkingLot3._meta.get_ancestor_link(Place).name,
|
||||
"parent")
|
||||
|
||||
def test_use_explicit_o2o_to_parent_from_abstract_model(self):
|
||||
self.assertEqual(ParkingLot4A._meta.pk.name, "parent")
|
||||
ParkingLot4A.objects.create(
|
||||
name="Parking4A",
|
||||
address='21 Jump Street',
|
||||
)
|
||||
|
||||
self.assertEqual(ParkingLot4B._meta.pk.name, "parent")
|
||||
ParkingLot4A.objects.create(
|
||||
name="Parking4B",
|
||||
address='21 Jump Street',
|
||||
)
|
||||
|
||||
def test_all_fields_from_abstract_base_class(self):
|
||||
"""
|
||||
Regression tests for #7588
|
||||
|
|
Loading…
Reference in New Issue