from django.db.models import Prefetch, Q from rest_framework import viewsets from rest_framework.decorators import api_view, permission_classes from rest_framework.permissions import IsAuthenticated from rest_framework.response import Response from .models import League, Player, PlayerSeasonStat, Team from .serializers import ( LeagueSerializer, PlayerDetailSerializer, PlayerListSerializer, TeamSerializer, ) STAT_FILTERS = { "games_played": "season_stats__games_played", "minutes_per_game": "season_stats__minutes_per_game", "points_per_game": "season_stats__points_per_game", "assists_per_game": "season_stats__assists_per_game", "rebounds_per_game": "season_stats__rebounds_per_game", "steals_per_game": "season_stats__steals_per_game", "blocks_per_game": "season_stats__blocks_per_game", "turnovers_per_game": "season_stats__turnovers_per_game", "field_goal_percentage": "season_stats__field_goal_percentage", "three_point_percentage": "season_stats__three_point_percentage", "free_throw_percentage": "season_stats__free_throw_percentage", "efficiency_rating": "season_stats__efficiency_rating", "true_shooting_percentage": "season_stats__true_shooting_percentage", "usage_percentage": "season_stats__usage_percentage", "total_points": "season_stats__total_points", "total_assists": "season_stats__total_assists", "total_rebounds": "season_stats__total_rebounds", } PLAYER_FILTERS = { "position": "position__iexact", "role": "role__icontains", "nationality": "nationality__icontains", "height_cm": "height_cm", "weight_kg": "weight_kg", "birth_year": "birth_year", } LOOKUPS = {"exact", "gte", "lte", "gt", "lt"} class PlayerViewSet(viewsets.ReadOnlyModelViewSet): permission_classes = [IsAuthenticated] def get_serializer_class(self): if self.action == "retrieve": return PlayerDetailSerializer return PlayerListSerializer def get_queryset(self): stats = PlayerSeasonStat.objects.select_related("league", "team", "season").order_by( "-efficiency_rating", "-points_per_game" ) queryset = ( Player.objects.select_related("current_team", "current_team__league") .prefetch_related(Prefetch("season_stats", queryset=stats, to_attr="prefetched_stats")) .distinct() ) params = self.request.query_params if query := params.get("q"): queryset = queryset.filter( Q(first_name__icontains=query) | Q(last_name__icontains=query) | Q(role__icontains=query) | Q(nationality__icontains=query) | Q(current_team__name__icontains=query) ) if league := params.get("league"): queryset = queryset.filter( Q(season_stats__league__code__iexact=league) | Q(season_stats__league__name__icontains=league) | Q(current_team__league__code__iexact=league) ) if region := params.get("region"): queryset = queryset.filter(season_stats__league__region__iexact=region) if team := params.get("team"): queryset = queryset.filter( Q(season_stats__team__name__icontains=team) | Q(current_team__name__icontains=team) ) if season := params.get("season"): queryset = queryset.filter(season_stats__season__label=season) for param, field in PLAYER_FILTERS.items(): if params.get(param): queryset = queryset.filter(**{field: params[param]}) for lookup in LOOKUPS - {"exact"}: key = f"{param}__{lookup}" if params.get(key): queryset = queryset.filter(**{f"{param}__{lookup}": params[key]}) for param, field in STAT_FILTERS.items(): if params.get(param): queryset = queryset.filter(**{field: params[param]}) for lookup in LOOKUPS - {"exact"}: key = f"{param}__{lookup}" if params.get(key): queryset = queryset.filter(**{f"{field}__{lookup}": params[key]}) return queryset.order_by("-season_stats__efficiency_rating", "-season_stats__points_per_game", "last_name") class LeagueViewSet(viewsets.ReadOnlyModelViewSet): permission_classes = [IsAuthenticated] queryset = League.objects.all() serializer_class = LeagueSerializer class TeamViewSet(viewsets.ReadOnlyModelViewSet): permission_classes = [IsAuthenticated] queryset = Team.objects.select_related("league").all() serializer_class = TeamSerializer @api_view(["GET"]) @permission_classes([IsAuthenticated]) def me(request): role = getattr(request.user.profile, "role", "viewer") return Response({"username": request.user.username, "role": role})