Browse Source

Fixed #27407 -- Made Model.delete(keep_parents=True) preserve parent reverse relationships.

Thanks Tim for the review.
Simon Charette 8 years ago
parent
commit
31a56e30cf
3 changed files with 16 additions and 0 deletions
  1. 4 0
      django/db/models/deletion.py
  2. 3 0
      docs/releases/1.10.4.txt
  3. 9 0
      tests/delete/tests.py

+ 4 - 0
django/db/models/deletion.py

@@ -206,7 +206,11 @@ class Collector(object):
                                  collect_related=False,
                                  reverse_dependency=True)
         if collect_related:
+            parents = model._meta.parents
             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 parents:
+                    continue
                 field = related.field
                 if field.remote_field.on_delete == DO_NOTHING:
                     continue

+ 3 - 0
docs/releases/1.10.4.txt

@@ -16,3 +16,6 @@ Bugfixes
 * Fixed incorrect ``app_label`` / ``model_name`` arguments for
   ``allow_migrate()`` in ``makemigrations`` migration consistency checks
   (:ticket:`27461`).
+
+* Made ``Model.delete(keep_parents=True)`` preserve parent reverse
+  relationships in multi-table inheritance (:ticket:`27407`).

+ 9 - 0
tests/delete/tests.py

@@ -359,6 +359,15 @@ class DeletionTests(TestCase):
         self.assertFalse(RChild.objects.filter(id=child.id).exists())
         self.assertTrue(R.objects.filter(id=parent_id).exists())
 
+    def test_delete_with_keeping_parents_relationships(self):
+        child = RChild.objects.create()
+        parent_id = child.r_ptr_id
+        parent_referent_id = S.objects.create(r=child.r_ptr).pk
+        child.delete(keep_parents=True)
+        self.assertFalse(RChild.objects.filter(id=child.id).exists())
+        self.assertTrue(R.objects.filter(id=parent_id).exists())
+        self.assertTrue(S.objects.filter(pk=parent_referent_id).exists())
+
     def test_queryset_delete_returns_num_rows(self):
         """
         QuerySet.delete() should return the number of deleted rows and a