[1.2.X] Fixed #13987 -- Ensure that the primary key is set correctly for all models that have concrete-abstract-concrete inheritance, not just the first model. Thanks to Aramgutang for the report and patch.

Backport of r15498 from trunk.

git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.2.X@15499 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
Russell Keith-Magee 2011-02-12 15:15:44 +00:00
parent c775f95abb
commit 48fe6099c0
3 changed files with 45 additions and 2 deletions

View File

@ -118,6 +118,12 @@ class Options(object):
# Promote the first parent link in lieu of adding yet another # Promote the first parent link in lieu of adding yet another
# field. # field.
field = self.parents.value_for_index(0) field = self.parents.value_for_index(0)
# Look for a local field with the same name as the
# first parent link. If a local field has already been
# created, use it instead of promoting the parent
already_created = [fld for fld in self.local_fields if fld.name == field.name]
if already_created:
field = already_created[0]
field.primary_key = True field.primary_key = True
self.setup_pk(field) self.setup_pk(field)
else: else:

View File

@ -146,3 +146,20 @@ class BachelorParty(AbstractEvent):
class MessyBachelorParty(BachelorParty): class MessyBachelorParty(BachelorParty):
pass pass
# Check concrete -> abstract -> concrete inheritance
class SearchableLocation(models.Model):
keywords = models.CharField(max_length=256)
class Station(SearchableLocation):
name = models.CharField(max_length=128)
class Meta:
abstract = True
class BusStation(Station):
bus_routes = models.CommaSeparatedIntegerField(max_length=128)
inbound = models.BooleanField()
class TrainStation(Station):
zone = models.IntegerField()

View File

@ -11,7 +11,7 @@ from models import (Place, Restaurant, ItalianRestaurant, ParkingLot,
ParkingLot2, ParkingLot3, Supplier, Wholesaler, Child, SelfRefParent, ParkingLot2, ParkingLot3, Supplier, Wholesaler, Child, SelfRefParent,
SelfRefChild, ArticleWithAuthor, M2MChild, QualityControl, DerivedM, SelfRefChild, ArticleWithAuthor, M2MChild, QualityControl, DerivedM,
Person, BirthdayParty, BachelorParty, MessyBachelorParty, Person, BirthdayParty, BachelorParty, MessyBachelorParty,
InternalCertificationAudit) InternalCertificationAudit, BusStation, TrainStation)
class ModelInheritanceTest(TestCase): class ModelInheritanceTest(TestCase):
@ -358,7 +358,7 @@ class ModelInheritanceTest(TestCase):
parties = list(p4.bachelorparty_set.all()) parties = list(p4.bachelorparty_set.all())
self.assertEqual(parties, [bachelor, messy_parent]) self.assertEqual(parties, [bachelor, messy_parent])
def test_11369(self): def test_abstract_verbose_name_plural_inheritance(self):
""" """
verbose_name_plural correctly inherited from ABC if inheritance chain verbose_name_plural correctly inherited from ABC if inheritance chain
includes an abstract model. includes an abstract model.
@ -386,3 +386,23 @@ class ModelInheritanceTest(TestCase):
], ],
attrgetter("pk") attrgetter("pk")
) )
def test_concrete_abstract_concrete_pk(self):
"""
Primary key set correctly with concrete->abstract->concrete inheritance.
"""
# Regression test for #13987: Primary key is incorrectly determined
# when more than one model has a concrete->abstract->concrete
# inheritance hierarchy.
self.assertEquals(
len([field for field in BusStation._meta.local_fields
if field.primary_key]),
1
)
self.assertEquals(
len([field for field in TrainStation._meta.local_fields
if field.primary_key]),
1
)
self.assertIs(BusStation._meta.pk.model, BusStation)
self.assertIs(TrainStation._meta.pk.model, TrainStation)