Fixed #20883 -- Made model inheritance find parent links in abstract parents

This commit is contained in:
Loic Bistuer 2013-08-12 18:30:38 +07:00 committed by Anssi Kääriäinen
parent dcdc579d16
commit 163a34ce4b
4 changed files with 47 additions and 6 deletions

View File

@ -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,

View File

@ -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
=====================================

View File

@ -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)

View File

@ -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