#21174 closed Bug (fixed)
Transaction handling broken in related manager modification methods
Reported by: | Anssi Kääriäinen | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.6-beta-1 |
Severity: | Normal | Keywords: | |
Cc: | loic@… | Triage Stage: | Accepted |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
Some of the related manager methods do multiple data-modifying operations but do not use any transaction management at all. This is clearly broken. This isn't a regression, so isn't a release blocker for that reason. However, this is a potential data corruption issue, so might be nice to fix for 1.6, too.
I am not sure how to test this. Maybe post_delete/save signals could be used to force exceptions and thus rollback.
EDIT: Forgot to add that a patch for some problematic methods available in https://github.com/django/django/pull/1684.
Change History (8)
comment:1 by , 11 years ago
Description: | modified (diff) |
---|---|
Triage Stage: | Unreviewed → Accepted |
comment:2 by , 11 years ago
Cc: | added |
---|
comment:3 by , 11 years ago
The .delete() code takes care of sending signals. Unfortunately it will also reload the instances back from DB to do so. It might be possible to use the lower level deletion APIs to send the already existing objects to be deleted in one go - no reload that way.
comment:4 by , 11 years ago
It just came back to mind that RelatedManager.remove()
for FK doesn't delete()
, it only SET_NULL
, there's a bit of an incompatibility between FK et GFK here...
So yeah for FK the signal incompatibility would be changing the fly of save()
by an update()
.
comment:5 by , 11 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
comment:7 by , 11 years ago
Fixed all the missing transactions I could find in related.py
: https://github.com/django/django/pull/2489.
This also has the benefit of fixing #21169 for GFK RelatedManager.remove().
The same applies to FK RelatedManager.remove() which also suffers from this issue. I would also implement it
self.using(db).filter(pk__in=[o.pk for o in objs]).delete()
, solving both transaction handling and default filtering at once.I've got the test cases for these stashed in a branch for #21169.
One thing to note though is the mild backward incompatibility: signals won't be fired anymore.