Fix: Prevent IntegrityError on user deletion by handling missing user#2233
Conversation
When a user deletes their account, the cascade deletes their WorkoutLogs and WorkoutSessions. These deletions trigger post_delete signals that attempt to recalculate the user's statistics via `UserStatisticsService`. This results in a `get_or_create` query attempting to insert a new UserStatistics record for a user that is simultaneously being deleted, yielding an IntegrityError. This commit resolves the transaction failure by explicitly checking if the user still exists before creating their statistics record, and safely catching `User.DoesNotExist` within the trophy signal handlers.
There was a problem hiding this comment.
Pull request overview
This PR addresses an IntegrityError that can occur during account deletion when cascade-deleted workout models trigger trophy/statistics recalculation after the User row is already gone, causing a foreign key violation when (re)creating UserStatistics.
Changes:
- Adds
User.DoesNotExisthandling in trophies signal handlers to short-circuit stats/trophy work when the user is missing. - Adds a user existence guard in
UserStatisticsService.get_or_create_statistics()before attemptingget_or_create().
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
wger/trophies/signals.py |
Swallows User.DoesNotExist in workout log/session signal handlers to avoid failing during cascade deletes. |
wger/trophies/services/statistics.py |
Adds an existence check to avoid creating UserStatistics for a user that no longer exists. |
Comments suppressed due to low confidence (1)
wger/trophies/signals.py:33
- Now that
Useris imported at module scope, the additionalfrom django.contrib.auth.models import Userinside_trigger_trophy_evaluation()becomes redundant and can be removed to avoid duplicated imports and potential confusion about whichUserreference is being used.
from django.contrib.auth.models import User
from django.db.models.signals import (
post_delete,
post_save,
)
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
Hey thanks for the PR (and glad you like the software!) Could you perhaps add a small test for this? |
…s handling deleted user Addresses review comment on PR wger-project#2233
|
Hey Roland, Thanks for the review and kind words! 😊 Added a small unit test for the get_or_create_statistics method handling the case where the user has been deleted (mocks the exists() check). Pushed the commit—let me know if this looks good or needs tweaks! Cheers, |
|
Ah, apologies for the previous slightly noisy comment—I'm testing an automated assistant workflow and a few placeholder tags leaked through. The test pushed earlier mocks the Let me know if this implementation fits the project's testing standards or if you'd prefer a different testing approach for the signal handlers! |
|
don't worry! I was thinking on adding a couple of logs, calling the trophy system so it does its thing and then making sure that the tests in |
…r feedback Implement Roland'\''s suggestion: create workout session records (logs), invoke trophy services, verify model delete succeeds without IntegrityError. Added logger statements. No mock in test_services.py needed to remove.
|
Hey Roland, Thanks for the spot-on suggestion! Creating session records (WorkoutSession), setting up trophy data, invoking the full trophy system (UserStatisticsService.update_statistics + TrophyService.evaluate_all_trophies), and verifying user.delete() succeeds without IntegrityError is fundamentally better—fully integrated with the real flow, no mocks needed. Added UserDeleteTrophyIntegrationTestCase.test_delete_user_with_trophy_records() to wger/core/tests/test_delete_user.py exactly as advised, with logger.info statements for visibility. Pushed to branch (rebased cleanly). Fingers crossed for CI! (with Syntra 🚀) |
|
mph, As a nitpick, you don't need to create variables like But then we should be done! 😅 |
|
Ah, just caught that the new test failed in CI with an |
|
merged, thanks! |
Glad i could help! and thank you for understanding how it came about, cheers! if you need a hand ping me! |
This PR addresses an
IntegrityErrorthat can occur during account deletion when cascade-deleted workout models trigger trophy/statistics recalculation after theUserrow is already gone, causing a foreign key violation when (re)creatingUserStatistics.Changes:
User.DoesNotExisthandling in trophies signal handlers.UserStatisticsService.get_or_create_statistics().User.DoesNotExistis cleanly caught.