diff --git a/django/db/models/deletion.py b/django/db/models/deletion.py index b1939f8b35..8d3fa5c92c 100644 --- a/django/db/models/deletion.py +++ b/django/db/models/deletion.py @@ -309,7 +309,10 @@ class Collector: protected_objects = defaultdict(list) for related in get_candidate_relations_to_delete(model._meta): # Preserve parent reverse relationships if keep_parents=True. - if keep_parents and related.model in model._meta.all_parents: + if ( + keep_parents + and related.model._meta.concrete_model in model._meta.all_parents + ): continue field = related.field on_delete = field.remote_field.on_delete diff --git a/tests/delete/models.py b/tests/delete/models.py index 4b627712bb..7f123b3396 100644 --- a/tests/delete/models.py +++ b/tests/delete/models.py @@ -32,6 +32,11 @@ class RChild(R): pass +class RProxy(R): + class Meta: + proxy = True + + class RChildChild(RChild): pass @@ -179,7 +184,7 @@ class RelToBase(models.Model): class Origin(models.Model): - pass + r_proxy = models.ForeignKey("RProxy", models.CASCADE, null=True) class Referrer(models.Model): diff --git a/tests/delete/tests.py b/tests/delete/tests.py index 7b9dcdb079..59140b5c62 100644 --- a/tests/delete/tests.py +++ b/tests/delete/tests.py @@ -34,6 +34,7 @@ from .models import ( RChild, RChildChild, Referrer, + RProxy, S, T, User, @@ -675,6 +676,14 @@ class DeletionTests(TestCase): ) signal.disconnect(receiver, sender=Referrer) + def test_keep_parents_does_not_delete_proxy_related(self): + r_child = RChild.objects.create() + r_proxy = RProxy.objects.get(pk=r_child.pk) + Origin.objects.create(r_proxy=r_proxy) + self.assertEqual(Origin.objects.count(), 1) + r_child.delete(keep_parents=True) + self.assertEqual(Origin.objects.count(), 1) + class FastDeleteTests(TestCase): def test_fast_delete_all(self):