Opened 11 years ago
Closed 11 years ago
#22594 closed Bug (fixed)
Content Type framework does not trigger Cascade delete
| Reported by: | JoseTomasTocino | Owned by: | nobody |
|---|---|---|---|
| Component: | contrib.contenttypes | Version: | 1.6 |
| Severity: | Normal | Keywords: | |
| Cc: | chk | Triage Stage: | Accepted |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
I've posted this question in StackOverflow (http://stackoverflow.com/questions/23528296/djangos-content-type-framework-does-not-trigger-cascade-delete) and given it looks like a bug, I've decided to post it here.
Suppose the following models:
class DeltaCheck(models.Model): logs = generic.GenericRelation('Log') title = models.CharField(max_length=50) owner = models.ForeignKey(User) class Log(models.Model): title = models.CharField(max_length=50) content_type = models.ForeignKey(ContentType) object_id = models.PositiveIntegerField() content_object = generic.GenericForeignKey('content_type', 'object_id')
If I create a DeltaCheck and a couple of Logs and then delete the DeltaCheck, the Logs are deleted as well:
In [7]: Log.objects.count() Out[7]: 10 In [8]: DeltaCheck.objects.get().delete() In [9]: Log.objects.count() Out[9]: 0
BUT if I delete the User (the field owner), the DeltaCheck gets deleted BUT not the Logs, look:
In [14]: Log.objects.count() Out[14]: 10 In [15]: DeltaCheck.objects.get().owner.delete() In [16]: DeltaCheck.objects.all() Out[16]: [] In [17]: Log.objects.count() Out[17]: 10
Is that proper behavior? I don't think so.
Change History (5)
comment:2 by , 11 years ago
| Cc: | added |
|---|
I'm able to reproduce the same issue with a similar database schema.
- django 1.6.1
- postgresql 9.1
As a workaround I've defined a pre_signal (but NOT empty as Jose says):
from django.db.models.signals import pre_delete
from django.dispatch import receiver
@receiver(pre_delete, sender=User)
def pre_delete_receiver(sender, instance, **kwargs):
## CODE TO DELETE RELATED OBJECTS
for delta in instance.deltachecks.all():
delta.logs.all().delete()
comment:3 by , 11 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|---|
| Type: | Uncategorized → Bug |
Hi,
I can also reproduce this issue (and indeed, having an empty signal fixes the issue).
For reference, cascade deletion of generic foreign keys is documented and only works if you have a reverse GenericRelation [1] (last two paragraphs).
The key to this issue probably lies in the fast_delete method [2] (note for example the line 126 that explains why things behave differently if there is a signal listening or not).
Thanks.
[1] https://docs.djangoproject.com/en/1.6/ref/contrib/contenttypes/#django.contrib.contenttypes.generic.GenericRelation
[2] https://github.com/django/django/blob/master/django/db/models/deletion.py#L110
comment:4 by , 11 years ago
comment:5 by , 11 years ago
| Resolution: | → fixed |
|---|---|
| Status: | new → closed |
I can confirm that #22998 fixes the issue, closing as fixed.
Wait... If I define an empty signal receiver, it works! (????) I've just added:
from django.db.models.signals import pre_delete, post_delete from django.dispatch import receiver @receiver(pre_delete) def pre_delete_receiver(**kwargs): passAnd now the deletion is performed...