Fix signals interfering with deleting a game with sessions
Django CI/CD / test (push) Successful in 2m29s
Django CI/CD / build-and-push (push) Failing after 1m31s

This commit is contained in:
2025-12-30 13:24:09 +01:00
parent 5cc1652002
commit 7032b8c7c7
2 changed files with 48 additions and 1 deletions
+9 -1
View File
@@ -20,7 +20,15 @@ def update_num_purchases(sender, instance, **kwargs):
@receiver([post_save, post_delete], sender=Session) @receiver([post_save, post_delete], sender=Session)
def update_game_playtime(sender, instance, **kwargs): def update_game_playtime(sender, instance, **kwargs):
game = instance.game # During cascade deletes the related Game may already have been removed.
# Use the FK id to look up the Game safely and bail out if it no longer exists.
game_pk = getattr(instance, "game_id", None)
if not game_pk:
return
game = Game.objects.filter(pk=game_pk).first()
if not game:
return
total_playtime = game.sessions.aggregate( total_playtime = game.sessions.aggregate(
total_playtime=Sum(F("duration_calculated") + F("duration_manual")) total_playtime=Sum(F("duration_calculated") + F("duration_manual"))
)["total_playtime"] )["total_playtime"]
+39
View File
@@ -0,0 +1,39 @@
import os
from datetime import datetime
from zoneinfo import ZoneInfo
import django
from django.test import TestCase
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "timetracker.settings")
django.setup()
from django.conf import settings
from games.models import Game, Session
ZONEINFO = ZoneInfo(settings.TIME_ZONE)
class SignalsTest(TestCase):
def test_deleting_game_with_sessions_does_not_raise(self):
# Create a game and attach a session to it
g = Game(name="Signal Test Game")
g.save()
s = Session(
game=g,
timestamp_start=datetime(2022, 9, 26, 14, 58, tzinfo=ZONEINFO),
timestamp_end=datetime(2022, 9, 26, 17, 38, tzinfo=ZONEINFO),
)
s.save()
# Sanity checks before delete
self.assertTrue(Game.objects.filter(pk=g.pk).exists())
self.assertEqual(g.sessions.count(), 1)
# Deleting the game should not raise (signals run during cascade)
g.delete()
# After deletion, the Game should be gone and no sessions remain
self.assertFalse(Game.objects.filter(pk=g.pk).exists())
self.assertEqual(Session.objects.filter(pk=s.pk).count(), 0)