Description

when django deletes an object, it also deletes all related objects.

it would be great to send the list of "to be deleted objects" in the pre_delete signal, because then a developer could implement in his application things like only-delete-object-when-there-are-no-related-objects (by raising an Exception in the listener-function), etc.

it can be implemented by an one-line change in db/models/query.py (patch attached).

This unfortunately needs to be more complicated to handle all the use cases for this feature. We need the following features:

Listeners should be able to modify the list of to-be-deleted objects. I think that'll work with your patch, but a test is needed to make sure that happens.

Because each doomed object gets a signal sent listener code might end up running multiple times. So we might need to figure out which objects have already been signaled. We could avoid a duplicate list (and the duplicate memory that would require) with some other lightweight structure -- perhaps the list of objects-to-delete could be a list of (object, has_been_notified)?

Another option to avoid duplicated callbacks would be an initial bulk-pre-delete signal (that is, use the same signal but with instance=None and instance_list=list_of_doomed_objects.

We also need to verify that we can in fact implement ON DELETE CASCADE-like behavior with this. If not, it's something of a worthless addition.

honestly, _please_ implement this (by merging this patch or calling the default Manager delete method, I won't be picky about this)

with the current code base (unless there is some magic hidden in db/models/query.py ...) i found no possibility to prevent a object from being deleted - apart from creating an ON DELETE - Trigger in the DB that silently prevents the deletion of a record

this is, however, not possible in all environments (if all databases were full-featured, this whole hack would not need to exist ...), and leads to unnecessary separation/fragmentation of logic. so please fix this issue one way or another

the code is untested, but i'm doing something very similar and it works.
if you want to make it 100% safe, you have to run it in a serializable-transaction unfortunately :(
otherwise it could happen, that the call to _collect_sub_objects returns
that all is fine, but while the code proceeds to delete-the-object,
some other process already inserted new "dependent" objects,
and those will get deleted.

yes, it contains a call to a privateundocumented method.
no, afaik no other way exists.

Related: #6870. My two cents is that the signal's arguments are fine as-is, it just needs to be called at an earlier point in time. Signals are simple and elegant; they tell you just enough information to find the rest of the information you might want. Adding the list of to-be-deleted objects is unnecessary because a signal listener could create this list without the signal including it.

Sending a list of related objects to be deleted with the pre_delete signal is fraught with complications, given that the pre_delete signal is sent once for every individual object to be deleted. Either objects get sent as part of the related-list potentially many times over (in which case how do you reconcile conflicts if the listener in one case removes the object and in another case doesn't?), or you have to make some arbitrary decisions about when a given object is included or not.

In any case, now that #7539 is fixed, all of the justifying use-cases here have workable alternatives.