Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how does SOFT_DELETE_CASCADE work? #202

Open
fcoppey opened this issue Mar 25, 2022 · 5 comments
Open

how does SOFT_DELETE_CASCADE work? #202

fcoppey opened this issue Mar 25, 2022 · 5 comments

Comments

@fcoppey
Copy link

fcoppey commented Mar 25, 2022

let’s say I have 2 models A and B, B has a foreign key pointing to A and other have soft delete with policy SOFT_DELETE_CASCADE.

If I soft delete an object in A, then the related object in B gets soft deleted as well BUT it seems its foreign key field point to A is set to NULL... which loses the link between object A and object B when I later want to undelete object A.

Is it the intended behaviour?

@odin1in
Copy link

odin1in commented Mar 20, 2023

I have the same issue. After I check the Django & safedelete source code, this is because you set the Null=True in your model.

https://docs.djangoproject.com/en/3.2/_modules/django/db/models/deletion/

# update fields (SET, SET_DEFAULT or SET_NULL)
for model, instances_for_fieldvalues in collector.field_updates.items():
if django.VERSION[0] > 4 or (django.VERSION[0] == 4 and django.VERSION[1] >= 2):
# as of 4.2 field_updates values is a list rather than a dictionary
(field, value) = model
instances_list = instances_for_fieldvalues
model = instances_list[0].__class__
updates = []
objs = []
for instances in instances_list:
if isinstance(instances, models.QuerySet):
updates.append(instances)
else:
objs.extend(instances)
if updates:
combined_updates = reduce(or_, updates)
combined_updates.update(**{field.name: value})
if objs:
query = models.sql.UpdateQuery(model)
query.update_batch(
list({obj.pk for obj in instances_list}), {field.name: value}, collector.using
)
else:
for (field, value), instances in instances_for_fieldvalues.items():
query = models.sql.UpdateQuery(model)
query.update_batch(
[obj.pk for obj in instances],
{field.name: value},
collector.using,
)

@fcoppey
Copy link
Author

fcoppey commented Mar 24, 2023

this is quit annoying as I must keep Null=True for some models, is there a workaround?

@fcoppey
Copy link
Author

fcoppey commented Mar 25, 2023

I’ve found a workaround by saving the pk list of related soft deleted objects before the soft deletion and then reassigning the parent id to these after the soft deletion... quite cumbersome. is any willing to make a patch for this bug? my level of coding is not high enough unfortunately... @Gagaro ?

@Gagaro
Copy link
Member

Gagaro commented Mar 27, 2023

Indeed I'm not sure how to fix that, maybe we should have our own CASCADE which does not set the other field as null.

I'll gladly review a PR if someone is willing to try and patch this.

@tuky
Copy link

tuky commented May 5, 2023

Having this would be great. For now we are stuck with _safedelete_policy = SOFT_DELETE. Also we have a regular model R that is related to a SafeDeleteModel S via ForeignKey. And this regular model R should be hard deleted, if the related instance of S is hard deleted and if S is soft deleted, R should not be touched.

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

No branches or pull requests

4 participants