Opened 5 years ago
Last modified 5 years ago
#31600 closed Bug
Calling .delete() on a queryset doesn't delete related objects — at Version 3
| Reported by: | אורי | Owned by: | nobody |
|---|---|---|---|
| Component: | Database layer (models, ORM) | Version: | dev |
| Severity: | Normal | Keywords: | |
| Cc: | Triage Stage: | Unreviewed | |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | no |
| Easy pickings: | no | UI/UX: | no |
Description (last modified by )
I created a new test and it had users and I deleted them:
User.objects.all().exclude(pk=self.user_1.pk).delete()
The User model has related models with on_delete=models.CASCADE which should be deleted as well.
But in my test, I got this exception:
======================================================================
ERROR: test_like_list_views_titles_with_empty_lists (speedy.match.likes.tests.test_views.LikeListViewsEnglishTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "env\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
return self.cursor.execute(sql)
psycopg2.errors.ForeignKeyViolation: insert or update on table "net_accounts_siteprofile" violates foreign key constraint "net_accounts_sitepro_user_id_c96775a1_fk_accounts_"
DETAIL: Key (user_id)=(403828609159078) is not present in table "accounts_user".
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "env\lib\site-packages\django\test\testcases.py", line 274, in __call__
self._post_teardown()
File "env\lib\site-packages\django\test\testcases.py", line 1009, in _post_teardown
self._fixture_teardown()
File "env\lib\site-packages\django\test\testcases.py", line 1177, in _fixture_teardown
connections[db_name].check_constraints()
File "env\lib\site-packages\django\db\backends\postgresql\base.py", line 276, in check_constraints
self.cursor().execute('SET CONSTRAINTS ALL IMMEDIATE')
File "env\lib\site-packages\django\db\backends\utils.py", line 68, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
File "env\lib\site-packages\django\db\backends\utils.py", line 77, in _execute_with_wrappers
return executor(sql, params, many, context)
File "env\lib\site-packages\django\db\backends\utils.py", line 86, in _execute
return self.cursor.execute(sql, params)
File "env\lib\site-packages\django\db\utils.py", line 90, in __exit__
raise dj_exc_value.with_traceback(traceback) from exc_value
File "env\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
return self.cursor.execute(sql)
django.db.utils.IntegrityError: insert or update on table "net_accounts_siteprofile" violates foreign key constraint "net_accounts_sitepro_user_id_c96775a1_fk_accounts_"
DETAIL: Key (user_id)=(403828609159078) is not present in table "accounts_user".
----------------------------------------------------------------------
Ran 1 test in 7.425s
I think this exception is because the users I deleted. net_accounts_siteprofile refers to the SiteProfile model which should be deleted when deleting a user by on_delete=models.CASCADE .
I checked and eventually I found out that changing:
User.objects.all().exclude(pk=self.user_1.pk).delete()
To:
for user in User.objects.all().exclude(pk=self.user_1.pk):
user.delete()
Fixes the problem. But I expected related objects to be deleted by the first query too. Does it mean I can't safely delete users in bulk by .delete()? And if it does, how do I disable it so trying to delete users in bulk will raise an exception?
I would like either to fix the queryset bulk .delete() method to delete related objects too, or to completely disable bulk deletions in Django. Is there a simple way to define a manager which doesn't have this bulk delete feature?
Change History (3)
comment:1 by , 5 years ago
| Description: | modified (diff) |
|---|
comment:2 by , 5 years ago
comment:3 by , 5 years ago
| Description: | modified (diff) |
|---|
Hi,
Since it's open source you can see the code. I created a branch with the failing test. You can see the test on https://github.com/speedy-net/speedy-net/blob/uri_temp_temp_branch_2020-05-18_a/speedy/match/likes/tests/test_views.py#L366-L411 and the commit who causes it to fail on https://github.com/speedy-net/speedy-net/commit/d91bd29d465149ede7ff906e0982b21d6c4a712f . You can check the failing tests on Travis CI https://travis-ci.org/github/speedy-net/speedy-net/builds/688212117 and the passing tests without this commit on https://travis-ci.org/github/speedy-net/speedy-net/builds/688210140 .