Opened 5 years ago
Last modified 16 months ago
#26630 assigned Bug
Defered constraint checks flush after `post_delete` signal
Reported by: | Alex Madjar | Owned by: | Can Sarıgöl |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | master |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | yes |
Easy pickings: | no | UI/UX: | no |
Description
Repro steps:
- Use a database that supports
can_defer_constraint_checks
(tested on postgres) - Have a model (A) with a
null=True
ForeignKey or OneToOneField (F) to another model (B) - Connect a function to listen to
post_delete
on (B) that pulls objects of type (A) from the db (using a = A.objects.get... etc ) - Try to access a.F for an object a that used to be associated with the deleted instance of B that was just deleted
Expectation: a.F_id is None
Actually: a.F_id is the id of the deleted instance and a.F raises an ObjectDoesNotExist exception
Note: doesn't repro on fields where null=False
or on sqlite. My diagnosis is that A's field isn't being properly cleared (or A objects deleted in the case of on delete CASCADE) because the constraint checks aren't being flushed until _after_ the post_delete
signal fires
Attachments (1)
Change History (7)
comment:1 Changed 5 years ago by
comment:2 Changed 5 years ago by
If you could provide a test case for Django's test suite, that would be helpful.
comment:3 Changed 5 years ago by
Triage Stage: | Unreviewed → Accepted |
---|
Seems legitimate. I attached a sample project I used to reproduce. The first test method shows the failure.
comment:4 Changed 17 months ago by
Owner: | changed from nobody to Can Sarıgöl |
---|---|
Status: | new → assigned |
Version: | 1.9 → master |
comment:5 Changed 17 months ago by
Has patch: | set |
---|
comment:6 Changed 16 months ago by
Patch needs improvement: | set |
---|
Only tried on CASCADE deletes, I think it blames to this code - https://github.com/django/django/blob/master/django/db/models/deletion.py#L15