#9741 closed (duplicate)
generic relations: reverse chain of references not followed fully on delete
| Reported by: | Éric St-Jean | Owned by: | aljosa |
|---|---|---|---|
| Component: | Contrib apps | Version: | 1.0 |
| Severity: | Keywords: | genericrelation genericforeignkey | |
| Cc: | eric@…, malini@…, martin@… | Triage Stage: | Accepted |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description
If i have an object c, which has a genericforeignkey relation to b, which in turn has a genericforeignkey relation to a, and i delete a, b does get deleted, but not c. If i were to delete b, c does get deleted.
If these were foreign keys, the chain of reverse relations would get properly deleted, but for genericrelations, it only goes back 1 link.
from django.db import models
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes import generic
class A(models.Model):
t = models.CharField(max_length=50)
gr_b_reverse = generic.GenericRelation('GR_B')
class FK_B(models.Model):
"""An object with a foreign key, that we'll point to an A"""
fk = models.ForeignKey('A')
class FK_C(models.Model):
"""An object with a foreign key, that we'll point to a FK_B"""
fk = models.ForeignKey('FK_B')
class GR_B(models.Model):
"""An object with a generic key, that we'll point to an A"""
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_obj = generic.GenericForeignKey(ct_field="content_type",
fk_field="object_id")
gr_c_reverse = generic.GenericRelation('GR_C')
class GR_C(models.Model):
"""An object with a generic key, that we'll point to a GR_B
# test proper deletion of gr_c pointing to gr_b if we delete gr_b
>>> a=A.objects.create(t='foo')
>>> gr_b=GR_B.objects.create(content_obj=a)
>>> gr_c=GR_C.objects.create(content_obj=gr_b)
>>> gr_b.delete()
>>> print A.objects.all(), GR_B.objects.all(), GR_C.objects.all()
[<A: A object>] [] []
>>> a.delete()
# test proper deletion of gr_b pointing to a if we delete a
>>> a=A.objects.create(t='foo')
>>> gr_b=GR_B.objects.create(content_obj=a)
>>> a.delete()
>>> print A.objects.all(), GR_B.objects.all()
[] []
# test proper deletion of fk_b pointing to a, fk_c pointing to b, gr_b pointing
# to a, and gr_c pointing to gr_b if we delete a
>>> a=A.objects.create(t='foo')
>>> gr_b=GR_B.objects.create(content_obj=a)
>>> gr_c=GR_C.objects.create(content_obj=gr_b)
>>> fk_b=FK_B.objects.create(fk=a)
>>> fk_c=FK_C.objects.create(fk=fk_b)
>>> print A.objects.all(), GR_B.objects.all(), GR_C.objects.all(), FK_B.objects.all(), FK_C.objects.all()
[<A: A object>] [<GR_B: GR_B object>] [<GR_C: GR_C object>] [<FK_B: FK_B object>] [<FK_C: FK_C object>]
>>> a.delete()
>>> print A.objects.all(), GR_B.objects.all(), GR_C.objects.all(), FK_B.objects.all(), FK_C.objects.all()
[] [] [] [] []
# FAIL! we instead get:
# [] [] [<GR_C: GR_C object>] [] []
"""
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_obj = generic.GenericForeignKey(ct_field="content_type",
fk_field="object_id")
Attachments (1)
Change History (11)
by , 17 years ago
| Attachment: | gr_test.tgz added |
|---|
comment:1 by , 17 years ago
| Cc: | added; removed |
|---|
comment:2 by , 17 years ago
test output:
eric@pluto:~/akoha/sandbox/gr_test$ ./manage.py test gr_test_app
Creating test database...
Creating table auth_permission
Creating table auth_group
Creating table auth_user
Creating table auth_message
Creating table django_content_type
Creating table django_session
Creating table django_site
Creating table gr_test_app_a
Creating table gr_test_app_fk_b
Creating table gr_test_app_fk_c
Creating table gr_test_app_gr_b
Creating table gr_test_app_gr_c
Installing index for auth.Permission model
Installing index for auth.Message model
Installing index for gr_test_app.FK_B model
Installing index for gr_test_app.FK_C model
Installing index for gr_test_app.GR_B model
Installing index for gr_test_app.GR_C model
F
======================================================================
FAIL: Doctest: gr_test_app.models.GR_C
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/eric/django/django_src/django/test/_doctest.py", line 2180, in runTest
raise self.failureException(self.format_failure(new.getvalue()))
AssertionError: Failed doctest test for gr_test_app.models.GR_C
File "/home/eric/akoha/sandbox/gr_test/gr_test_app/models.py", line 25, in GR_C
----------------------------------------------------------------------
File "/home/eric/akoha/sandbox/gr_test/gr_test_app/models.py", line 54, in gr_test_app.models.GR_C
Failed example:
print A.objects.all(), GR_B.objects.all(), GR_C.objects.all(), FK_B.objects.all(), FK_C.objects.all()
Expected:
[] [] [] [] []
Got:
[] [] [<GR_C: GR_C object>] [] []
----------------------------------------------------------------------
Ran 1 test in 0.041s
FAILED (failures=1)
Destroying test database...
comment:3 by , 17 years ago
python + django version tested with:
Python 2.5.2 (r252:60911, Jul 31 2008, 17:28:52) [GCC 4.2.3 (Ubuntu 4.2.3-2ubuntu7)] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> import django >>> django.VERSION (1, 1, 0, 'alpha', 0)
which is rev 9549.
also tried with (1, 0, 'final') with the exact same result.
MySQL is 5.0.51a-3ubuntu5.4
comment:4 by , 17 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:5 by , 17 years ago
| milestone: | → 1.1 |
|---|
comment:6 by , 17 years ago
| milestone: | 1.1 → 1.2 |
|---|
Pushing to 1.2. This is borderline, but at this late stage without a patch we'll have to live with this inconsistency for now. A custom Model.delete() method can be an acceptable workaround in these cases.
comment:7 by , 17 years ago
| Owner: | changed from to |
|---|
comment:8 by , 16 years ago
| Summary: | generic relations: reverse chain of references not followed fully yon delete → generic relations: reverse chain of references not followed fully on delete |
|---|
comment:9 by , 16 years ago
| Resolution: | → duplicate |
|---|---|
| Status: | new → closed |
Closing as duplicate of #12953; this one was filed first, but the other already has a working patch with tests.
full project tree for test app