#27585 closed Bug (invalid)
ManyToMany relationship is cascading delete after being detached
Reported by: | Teresa | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.8 |
Severity: | Normal | Keywords: | ManyToMany, cascade, delete, remove |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Given two models A and B that have a many-to-many relationship, removing all of the As from a model B, then deleting B results in all of the As that should now be detached from B being deleted. This is happening inside of a single transaction, using an SQLite database backend, as well as a MySQL backend.
Below is code that will reproduce the issue:
class A(models.Model): bs = models.ManyToManyField(B, related_name='as') class B(models.Model): ... def delete_b_without_deleting_as(b): with transaction.atomic(): to_be_orphaned_as = [a for a in b.as.all()] for a in to_be_orphaned_as: b.as.remove(a) b.delete()
This results in both 'b' and all of the 'a's that had been a part of b.as.all() to be deleted from the database.
The expected behaviour would be for b.delete() to not cascade as it is a ManyToMany field, and in addition all of the 'a's have been detached from the relationship with 'b'. There is no reason for deleting 'b' to cascade and delete models that no longer have any relationship with 'b'.
Change History (6)
comment:1 by , 8 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
comment:2 by , 8 years ago
Resolution: | invalid |
---|---|
Status: | closed → new |
comment:3 by , 8 years ago
Could you please provide a sample app with models and tests we could download to reproduce? The example code doesn't run as b.as.all()
is a SyntaxError
.
comment:4 by , 8 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
comment:5 by , 4 years ago
This problem just happened to me on Django 2.2.12 in a migration. e.g.
Category = apps.get_model('blog', 'Category') cat = Category.objects.filter(name='Cat A').first() for article in list(cat.article_set.all()): cat.article_set.remove(article) # This deleted all articles that were in the category but were already removed() cat.delete()
comment:6 by , 4 years ago
Matt, could you provide a full set of models to reproduce.
I cannot reproduce on Django 2.2 and cascade deletion should not propagate this way through many-to-many relationships.
An additional detail:
The models also have a ManyToOne foreign key constraint. But when that relationship has also been removed, the now unattached 'a's are deleted.