Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

izquierdo
Copy link
Contributor

@timgraham timgraham changed the title Fixed #27272 -- Add a on_delete RESTRICT handler to allow cascading deletions while protecting direct ones Fixed #27272 -- Added an on_delete RESTRICT handler to allow cascading deletions while protecting direct ones. Oct 10, 2016
Copy link
Member

@timgraham timgraham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The admin has some custom delete stuff. Did you check that nothing is needed there? (django/contrib/admin/utils.py). Please uncheck "Patch needs improvement" on the ticket after updating the PR.

@charettes
Copy link
Member

The ProtectedError errors must be raised during the collection phase and not the deletion one.

@izquierdo
Copy link
Contributor Author

For ProtectedError to be raised during the collection phase, we need to know whether a call is the top-level call or not. Recursive calls to collect() cannot raise when they find restricted objects because those objects may be found through a different path by the caller. That's why I added the fail_on_restricted argument. Please let me know if this is acceptable.

Still need to fix the documentation build errors, and add another test case for the above potential problem about recursive calls not raising ProtectedError, so this is not ready for another review yet.

@timgraham
Copy link
Member

@izquierdo, do you plan to return to this soon or should we close it?

@izquierdo
Copy link
Contributor Author

I'm sorry for temporarily suspending work on this, I will return to it soon. Please do not close.

Copy link
Member

@ngnpope ngnpope left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't tried this out, but I ran into the need for this today. I've added a few initial comments here.

I'd also like to see tests to ensure that this works with more complex situations, e.g.

   C      R
A ─── B1 ─── X
│            │
└──── B2 ────┘
  C        C

(This is like having an extra model between Artist and Song.)

@izquierdo
Copy link
Contributor Author

Thank you for the review. Working on the extra requested tests and other comments, and will also rebase this on top of the latest.

@LuRsT
Copy link
Contributor

LuRsT commented Sep 17, 2019

Gentle reminder @izquierdo, will you be picking this one up again?

@izquierdo izquierdo force-pushed the 27272 branch 4 times, most recently from 4edb147 to b3d4da6 Compare September 21, 2019 05:26
@auvipy
Copy link
Contributor

auvipy commented Sep 21, 2019

just 2 flake8 errors

@izquierdo izquierdo force-pushed the 27272 branch 2 times, most recently from c681d22 to 77d19a8 Compare September 23, 2019 01:13
@izquierdo
Copy link
Contributor Author

I believe all comments have been addressed now.

This is something that should be discussed on the mailing list, but would it make sense to have a RestrictedError here for RESTRICT in place of ProtectedError?

Changed to RestrictedError but should I still open up a discussion in the mailing list?

@felixxm
Copy link
Member

felixxm commented Sep 23, 2019

@izquierdo I don't think that discussion is necessary. Please uncheck "Patch needs improvement" flag if you believe that all comments have been addressed.

Copy link
Member

@felixxm felixxm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@izquierdo Thanks for this patch 👍 I reviewed docs and left some comments. I'm going to review the rest of this patch, asap.

Copy link
Member

@felixxm felixxm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@izquierdo Thanks again for this patch 👍 We're quite close. Some tests are missing, please check my comments.

@izquierdo
Copy link
Contributor Author

Thank you for the review, added tests and addressed comments

@felixxm
Copy link
Member

felixxm commented Oct 14, 2019

Thanks for updates 👍 Can you check tests failures on MySQL and MariaDB? (delete.tests.OnDeleteTests.test_restrict_generic_foreign_key_and_no_fast_delete).

Copy link
Member

@felixxm felixxm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@izquierdo Thanks for updates 👍

I rebased from master, pushed minor edits, simplified tests in admin_views, moved adding add_dependency() to a separate commit. I'm still working on delete tests.

I left comments about add_dependency(). Can you take a look?

Please don't use force-push.

@izquierdo
Copy link
Contributor Author

Please don't use force-push.

I'm extremely sorry, I rebased on master and completely missed this comment before force-pushing. Please push again and I'll handle the comments from there.

@izquierdo
Copy link
Contributor Author

Recovered your commit and did one final force push to get back there

@felixxm
Copy link
Member

felixxm commented Oct 29, 2019

@izquierdo Can you take a look at my comments? ☝️

@izquierdo
Copy link
Contributor Author

Addressed comments

Copy link
Member

@felixxm felixxm left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@izquierdo Thanks for updates 👍 I squashed commit and push minor fixes to tests. We're quite close but I have few questions/concerns:

  • test_restrict_indirect_cascade Do we need this? I'm not sure how this path is different from test_restrict_path_cascade_indirect.
  • test_restrict_generic_foreign_key_and_no_fast_delete Can we test the same with ParentA? i.e. without the second structure with GenericRelation's.
  • test fail when I add ParentA on MySQL/MariaDB: django.db.utils.IntegrityError: (1451, 'Cannot delete ....
  • Do we know why we need a special workaround for MySQL/MariaDB? maybe it's related with the fact that constraints checks cannot be deferred, in this case we should use connections[using].features.can_defer_constraint_checks. Otherwise, we probably need another database feature.

Reminder: please don't use force-push it will be easier to review amendments.

@izquierdo
Copy link
Contributor Author

test_restrict_indirect_cascade Do we need this? I'm not sure how this path is different from test_restrict_path_cascade_indirect.

The main difference is that there's an extra model between the object from which deletion started and the restricted object, instead of a single model with two instances. This was added as requested earlier. Other than that the diamond structure is the same. I do believe it's better to test both situations but this can be removed if you disagree.

Another difference is that test_restrict_indirect_cascade tries to delete the intermediate model (B1) whereas test_restrict_path_cascade_indirect doesn't try to (its intermediate model is R). But this scenario is tested in test_restrict too so I don't think it's necessary to add it to test_restrict_path_cascade_indirect if we end up removing test_restrict_indirect_cascade.

@izquierdo
Copy link
Contributor Author

test fail when I add ParentA on MySQL/MariaDB: django.db.utils.IntegrityError: (1451, 'Cannot delete ....

This happens because of a missing dependency and is also fixed by b1a586f

@izquierdo
Copy link
Contributor Author

izquierdo commented Nov 17, 2019

Do we know why we need a special workaround for MySQL/MariaDB? maybe it's related with the fact that constraints checks cannot be deferred, in this case we should use connections[using].features.can_defer_constraint_checks. Otherwise, we probably need another database feature.

This comment suggests that the sorting is indeed because constraint checks cannot be deferred:

# if possible, bring the models in an order suitable for databases that
# don't support transactions or cannot defer constraint checks until the
# end of a transaction.

But it's not just a workaround for that -- it's also used to dispatch signals in the right order. If you apply the following patch to master:

diff --git a/django/db/models/deletion.py b/django/db/models/deletion.py
index 62afff1f50..6fa9e53bdc 100644
--- a/django/db/models/deletion.py
+++ b/django/db/models/deletion.py
@@ -298,7 +298,8 @@ class Collector:
         # if possible, bring the models in an order suitable for databases that
         # don't support transactions or cannot defer constraint checks until the
         # end of a transaction.
-        self.sort()
+        if not connections[self.using].features.can_defer_constraint_checks:
+            self.sort()
         # number of objects deleted for each model label
         deleted_counter = Counter()

then you get failures on test_relational_post_delete_signals_happen_before_parent_object and test_deletion_order when not using MySQL/MariaDB.

Should I update the docstring on sort() to clarify this?

@izquierdo
Copy link
Contributor Author

The latest comments are addressed, please let me know what to do regarding:

  • Removal of test_restrict_indirect_cascade
  • Docstring on sort()
  • Any other comments

Thank you for the review, I appreciate your thoroughness.

@felixxm
Copy link
Member

felixxm commented Nov 19, 2019

@izquierdo Thanks for your patience and explanations 🥇 . We're ready to merge 🚀 🎉

@felixxm felixxm merged commit 89abecc into django:master Nov 19, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants