From 67cf5efa31acb2916034afb15610b700695dfcb0 Mon Sep 17 00:00:00 2001 From: Simon Charette Date: Mon, 28 Mar 2016 14:14:24 -0400 Subject: [PATCH] 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. --- django/db/models/base.py | 10 +++++++++- docs/releases/1.9.5.txt | 3 +++ tests/model_inheritance/tests.py | 20 ++++++++++++++++++-- 3 files changed, 30 insertions(+), 3 deletions(-) diff --git a/django/db/models/base.py b/django/db/models/base.py index 8cc9599782..1f2f64fff2 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -244,13 +244,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) diff --git a/docs/releases/1.9.5.txt b/docs/releases/1.9.5.txt index 6f073c5c07..7c50e4883d 100644 --- a/docs/releases/1.9.5.txt +++ b/docs/releases/1.9.5.txt @@ -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`). diff --git a/tests/model_inheritance/tests.py b/tests/model_inheritance/tests.py index 9b52b91d0e..72079a50f8 100644 --- a/tests/model_inheritance/tests.py +++ b/tests/model_inheritance/tests.py @@ -4,9 +4,9 @@ from operator import attrgetter 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.test.utils import CaptureQueriesContext, isolate_apps from django.utils import six from .models import ( @@ -140,6 +140,22 @@ class ModelInheritanceTests(TestCase): m = MixinModel() self.assertEqual(m.other_attr, 1) + @isolate_apps('model_inheritance') + def test_abstract_parent_link(self): + class A(models.Model): + pass + + class B(A): + a = models.OneToOneField('A', parent_link=True, on_delete=models.CASCADE) + + class Meta: + abstract = True + + class C(B): + pass + + self.assertIs(C._meta.parents[A], C._meta.get_field('a')) + class ModelInheritanceDataTests(TestCase): @classmethod