Loading django/db/models/base.py +16 −5 Original line number Diff line number Diff line Loading @@ -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'): Loading @@ -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, Loading docs/releases/1.7.txt +3 −0 Original line number Diff line number Diff line Loading @@ -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 ===================================== Loading tests/model_inheritance_regress/models.py +13 −0 Original line number Diff line number Diff line Loading @@ -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) Loading tests/model_inheritance_regress/tests.py +15 −1 Original line number Diff line number Diff line Loading @@ -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): Loading Loading @@ -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 Loading
django/db/models/base.py +16 −5 Original line number Diff line number Diff line Loading @@ -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'): Loading @@ -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, Loading
docs/releases/1.7.txt +3 −0 Original line number Diff line number Diff line Loading @@ -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 ===================================== Loading
tests/model_inheritance_regress/models.py +13 −0 Original line number Diff line number Diff line Loading @@ -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) Loading
tests/model_inheritance_regress/tests.py +15 −1 Original line number Diff line number Diff line Loading @@ -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): Loading Loading @@ -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