From c6e431a0d36c36bbd2a721b1c2722cf565b4d2f9 Mon Sep 17 00:00:00 2001 From: Laurent Date: Mon, 28 Jul 2025 14:56:21 +0200 Subject: [PATCH] improved performance with claude --- tournaments/models/tournament.py | 41 +++++++++++++++++--------- tournaments/views.py | 50 ++++++++++++++++++++++++++++---- 2 files changed, 72 insertions(+), 19 deletions(-) diff --git a/tournaments/models/tournament.py b/tournaments/models/tournament.py index 5780cfa..5485003 100644 --- a/tournaments/models/tournament.py +++ b/tournaments/models/tournament.py @@ -503,10 +503,13 @@ class Tournament(BaseModel): match_groups = [] if group_stage_id: - group_stage = self.group_stages.filter(id=group_stage_id).first() - match_groups.append(self.group_stage_match_group(group_stage, broadcasted, hide_empty_matches=False)) + # Use prefetched data instead of additional query + group_stage = next((gs for gs in self.group_stages.all() if str(gs.id) == group_stage_id), None) + if group_stage: + match_groups.append(self.group_stage_match_group(group_stage, broadcasted, hide_empty_matches=False)) elif round_id: - round = self.rounds.filter(id=round_id).first() + # Use prefetched data instead of additional query + round = next((r for r in self.rounds.all() if str(r.id) == round_id), None) if round and display_brackets is True: match_groups = self.round_match_groups(round, broadcasted, hide_empty_matches=False) else: @@ -518,13 +521,17 @@ class Tournament(BaseModel): groups = [] if self.display_matches(): - rounds = self.rounds.filter(parent=None, group_stage_loser_bracket=False).all().order_by('index').prefetch_related('matches', 'matches__team_scores', 'matches__team_scores__team_registration', 'matches__team_scores__team_registration__player_registrations') - for round in rounds: + # Use already prefetched rounds to avoid additional queries + bracket_rounds = [r for r in self.rounds.all() if r.parent is None and not r.group_stage_loser_bracket] + bracket_rounds.sort(key=lambda r: r.index) + for round in bracket_rounds: groups.extend(self.round_match_groups(round, broadcasted, hide_empty_matches=True)) if self.display_group_stages(): - rounds = self.rounds.filter(parent=None, group_stage_loser_bracket=True).all().order_by('index').prefetch_related('matches', 'matches__team_scores', 'matches__team_scores__team_registration', 'matches__team_scores__team_registration__player_registrations') - for round in rounds: + # Use already prefetched rounds to avoid additional queries + loser_bracket_rounds = [r for r in self.rounds.all() if r.parent is None and r.group_stage_loser_bracket] + loser_bracket_rounds.sort(key=lambda r: r.index) + for round in loser_bracket_rounds: groups.extend(self.round_match_groups(round, broadcasted, hide_empty_matches=True)) group_stages = sorted(self.sorted_group_stages(), key=lambda s: (-s.step, s.index)) @@ -609,19 +616,25 @@ class Tournament(BaseModel): return [gs.live_group_stages() for gs in group_stages] def sorted_group_stages(self): - # Get all group stages and sort by step (descending) and index (ascending) - group_stages = self.group_stages.all().order_by('-step', 'index').prefetch_related('matches', 'matches__team_scores', 'matches__team_scores__team_registration', 'matches__team_scores__team_registration__player_registrations') + # Use already prefetched group stages to avoid additional queries + group_stages = list(self.group_stages.all()) + group_stages.sort(key=lambda gs: (-gs.step, gs.index)) # List to collect live group stages from finished steps filtered = [] + steps_completed = set() for group_stage in group_stages: if group_stage.step > 0: - # Check the previous step's group stages - previous_step_group_stages = self.group_stages.filter(step=group_stage.step - 1) - - # Check if all previous step group stages are completed - if all(gs.is_completed() for gs in previous_step_group_stages): + # Check the previous step's group stages using already loaded data + prev_step = group_stage.step - 1 + if prev_step not in steps_completed: + previous_step_group_stages = [gs for gs in group_stages if gs.step == prev_step] + # Check if all previous step group stages are completed + if previous_step_group_stages and all(gs.is_completed() for gs in previous_step_group_stages): + steps_completed.add(prev_step) + + if prev_step in steps_completed: filtered.append(group_stage) else: # Always include step 0 diff --git a/tournaments/views.py b/tournaments/views.py index 39b3817..1108108 100644 --- a/tournaments/views.py +++ b/tournaments/views.py @@ -290,17 +290,57 @@ def event(request, event_id): def tournament(request, tournament_id): - tournament = get_object_or_404(Tournament, pk=tournament_id) + tournament = get_object_or_404( + Tournament.objects.select_related('event') + .prefetch_related( + 'rounds', + 'rounds__children', + 'rounds__matches__team_scores__team_registration__player_registrations__player', + 'group_stages__matches__team_scores__team_registration__player_registrations__player', + 'rounds__children__matches__team_scores__team_registration__player_registrations__player' + ), + pk=tournament_id + ) round_id = request.GET.get('round') group_stage_id = request.GET.get('group_stage') - match_groups = tournament.match_groups(False, group_stage_id, round_id) - bracket_rounds = tournament.rounds.filter(parent=None, group_stage_loser_bracket=False).order_by('-index') - rounds = list(tournament.rounds.filter(group_stage_loser_bracket=True)) + # Cache rounds and group stages to avoid repeated queries + all_rounds = list(tournament.rounds.all()) + all_group_stages = list(tournament.group_stages.all()) + + # Filter rounds efficiently + bracket_rounds = [r for r in all_rounds if r.parent is None and not r.group_stage_loser_bracket] + loser_bracket_rounds = [r for r in all_rounds if r.group_stage_loser_bracket] + + # Sort rounds by index (descending for bracket_rounds) + bracket_rounds.sort(key=lambda r: r.index, reverse=True) + loser_bracket_rounds.sort(key=lambda r: r.index) + + rounds = list(loser_bracket_rounds) rounds.extend(bracket_rounds) - group_stages = sorted(tournament.sorted_group_stages(), key=lambda s: (s.step, s.index)) + # Optimize group stage filtering with step completion caching + all_group_stages.sort(key=lambda gs: (-gs.step, gs.index)) + filtered_group_stages = [] + steps_completed = {} + + for group_stage in all_group_stages: + if group_stage.step == 0: + filtered_group_stages.append(group_stage) + elif group_stage.step > 0: + prev_step = group_stage.step - 1 + if prev_step not in steps_completed: + prev_step_stages = [gs for gs in all_group_stages if gs.step == prev_step] + steps_completed[prev_step] = prev_step_stages and all(gs.is_completed() for gs in prev_step_stages) + + if steps_completed[prev_step]: + filtered_group_stages.append(group_stage) + + group_stages = sorted(filtered_group_stages, key=lambda s: (s.step, s.index)) + + # Get match groups with optimized data + match_groups = tournament.match_groups(False, group_stage_id, round_id) if tournament.display_matches() or tournament.display_group_stages(): return render(request, 'tournaments/matches.html', {