django-postgres-extra icon indicating copy to clipboard operation
django-postgres-extra copied to clipboard

Add support for native cascading deletes

Open Photonios opened this issue 7 years ago • 4 comments

Photonios avatar Jun 08 '17 11:06 Photonios

Django emulates cascades by fetching all the related objects and deleting them instead of relying on the DB to do this.

Photonios avatar Jun 08 '17 11:06 Photonios

One likely pain point for this is figuring out the Right Thing to do with regard to signals. Django itself will call the pre_delete and post_delete handlers for each object on cascade deletes. That really wouldn't be reasonable with db-level cascades. I'm not sure what the best way to handle that is, or if perhaps there's a way to throw an error if there are registered post_delete signals combined with the cascade deletes, so that at least it will fail loudly.

ryanhiebert avatar Feb 21 '19 19:02 ryanhiebert

That's a very good point. One of the things you'd most likely have to give up on with native DB cascading is Django signals. I always envisioned this as a feature that provides an alternative method to bulk to delete records. With a certain price to pay; not having signals.

One way of doing this would be to provide a custom query set method such as:

MyModel.objects.delete_native_cascade()

The name in the example above is not greatest, but it makes a clear distinction between Django's standard delete method and a native delete.

It might also be possible to ask the database to return the primary keys of the records that are going to be deleted. That would allow us to to still invoke some kind of signal.

Anyhow, any ideas on how to implement this feature are more than welcome. I apreciate you taking the time to think about this. It certainely is something that we have to think about.

Photonios avatar Feb 22 '19 06:02 Photonios

Maybe it would be a good option to add a custom foreign key definition that creates FK on the database with Postgres specific options, like CASCADE deletion (ON DELETE CASCADE in the field definition on the database level). let's name it:

PostgresForeginKey with can be called with parameter PostgresForeginKey(native_on_delete=CASCADE)

By that, the Database will handle cascade deletions. Next, we can add an implementation of the delete_native_cascade method which generates a simple bulk DELETE query. But before it generates it, it checks whether the related model point to it via our PostgresFields, if not, then we can raise an exception (operation not supported).

BezBartek avatar May 27 '22 15:05 BezBartek