Fix signals interfering with deleting a game with sessions
This commit is contained in:
+9
-1
@@ -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"]
|
||||||
|
|||||||
@@ -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)
|
||||||
Reference in New Issue
Block a user