[1.9.x] Fixed #26413 -- Fixed a regression with abstract model inheritance and explicit parent links.

Thanks Trac alias trkjgrdg for the report and Tim for investigation and review.

Backport of 67cf5efa31acb2916034afb15610b700695dfcb0 from master
This commit is contained in:
Simon Charette 2016-03-28 14:14:24 -04:00
parent 97c5539a81
commit 026574e03c
3 changed files with 34 additions and 2 deletions

View File

@ -245,13 +245,21 @@ class ModelBase(type):
field = None
new_class._meta.parents[base] = field
else:
base_parents = base._meta.parents.copy()
# .. and abstract ones.
for field in parent_fields:
new_field = copy.deepcopy(field)
new_class.add_to_class(field.name, new_field)
# Replace parent links defined on this base by the new
# field as it will be appropriately resolved if required.
if field.one_to_one:
for parent, parent_link in base_parents.items():
if field == parent_link:
base_parents[parent] = new_field
# Pass any non-abstract parent classes onto child.
new_class._meta.parents.update(base._meta.parents)
new_class._meta.parents.update(base_parents)
# Inherit managers from the abstract base classes.
new_class.copy_managers(base._meta.abstract_managers)

View File

@ -40,3 +40,6 @@ Bugfixes
* Restored the functionality of the admin's ``raw_id_fields`` in
``list_editable`` (:ticket:`26387`).
* Fixed a regression with abstract model inheritance and explicit parent links
(:ticket:`26413`).

View File

@ -2,9 +2,10 @@ from __future__ import unicode_literals
from operator import attrgetter
from django.apps.registry import Apps
from django.core.exceptions import FieldError, ValidationError
from django.core.management import call_command
from django.db import connection
from django.db import connection, models
from django.test import TestCase, TransactionTestCase
from django.test.utils import CaptureQueriesContext
from django.utils import six
@ -130,6 +131,26 @@ class ModelInheritanceTests(TestCase):
m = MixinModel()
self.assertEqual(m.other_attr, 1)
def test_abstract_parent_link(self):
test_apps = Apps(['model_inheritance'])
class A(models.Model):
class Meta:
apps = test_apps
class B(A):
a = models.OneToOneField('A', parent_link=True, on_delete=models.CASCADE)
class Meta:
apps = test_apps
abstract = True
class C(B):
class Meta:
apps = test_apps
self.assertIs(C._meta.parents[A], C._meta.get_field('a'))
class ModelInheritanceDataTests(TestCase):
@classmethod