From b88a61e48960e38c3c8669aa47bcb0dd142fdf6c Mon Sep 17 00:00:00 2001 From: Muhammed Zafar Date: Tue, 17 Oct 2023 22:01:04 +0530 Subject: [PATCH] [OPTIM] Leaderboard patches (#1348) --- api/leaderboard/leaderboard_view.py | 34 ++++++++++++++++------------- api/leaderboard/serializers.py | 26 +++++++++++++++++----- 2 files changed, 39 insertions(+), 21 deletions(-) diff --git a/api/leaderboard/leaderboard_view.py b/api/leaderboard/leaderboard_view.py index 3f206840..65811990 100644 --- a/api/leaderboard/leaderboard_view.py +++ b/api/leaderboard/leaderboard_view.py @@ -1,7 +1,8 @@ -from django.db.models import Sum, F, Value, OuterRef, Subquery, Count, Q +from django.db.models import Sum, F, Value, OuterRef, Subquery, Count, Q, Prefetch from django.db.models.functions import Concat, Coalesce from rest_framework.views import APIView import datetime +from . import serializers from db.organization import Organization, UserOrganizationLink from db.user import User @@ -12,14 +13,6 @@ class StudentsLeaderboard(APIView): def get(self, request): - user_college = ( - UserOrganizationLink.objects.filter( - user_id=OuterRef("id"), org__org_type=OrganizationType.COLLEGE.value - ) - .order_by("id") - .values("org__title")[:1] - ) - students_leaderboard = ( User.objects.filter( user_organization_link_user__org__org_type=OrganizationType.COLLEGE.value, @@ -28,14 +21,25 @@ def get(self, request): active=True, ) .distinct() - .values( - total_karma=F("wallet_user__karma"), - full_name=Concat(F("first_name"), Value(" "), F("last_name")), - institution=Subquery(user_college), + .select_related("wallet_user") + .prefetch_related( + Prefetch( + "user_organization_link_user", + queryset=UserOrganizationLink.objects.filter( + org__org_type=OrganizationType.COLLEGE.value + ).select_related("org"), + to_attr="colleges" + ) ) - .order_by("-total_karma")[:20] + .order_by("-wallet_user__karma")[:20] + ) + serialized_students_leaderboard = serializers.StudentLeaderboardSerializer( + students_leaderboard, many=True ) - return CustomResponse(response=students_leaderboard).get_success_response() + + return CustomResponse( + response=serialized_students_leaderboard.data + ).get_success_response() class StudentsMonthlyLeaderboard(APIView): diff --git a/api/leaderboard/serializers.py b/api/leaderboard/serializers.py index fb591aba..e35a4dc3 100644 --- a/api/leaderboard/serializers.py +++ b/api/leaderboard/serializers.py @@ -5,6 +5,7 @@ from db.organization import UserOrganizationLink from db.task import KarmaActivityLog +from db.user import User from utils.types import OrganizationType from utils.utils import DateTimeUtils @@ -46,12 +47,12 @@ def get_active_members(self, obj): def get_total_karma(self, obj): return ( - obj.org.user_organization_link_org.filter( - org__org_type=OrganizationType.COLLEGE.value, - verified=True, - user__wallet_user__isnull=False, - ).aggregate(total_karma=Sum("user__wallet_user__karma"))["total_karma"] - or 0 + obj.org.user_organization_link_org.filter( + org__org_type=OrganizationType.COLLEGE.value, + verified=True, + user__wallet_user__isnull=False, + ).aggregate(total_karma=Sum("user__wallet_user__karma"))["total_karma"] + or 0 ) def get_rank(self, obj): @@ -74,3 +75,16 @@ def get_rank(self, obj): keys_list = list(sorted_rank_dict.keys()) position = keys_list.index(obj.org.id) return position + 1 + + +class StudentLeaderboardSerializer(serializers.ModelSerializer): + institution = serializers.SerializerMethodField() + total_karma = serializers.IntegerField(source="wallet_user.karma", default=0) + full_name = serializers.CharField(source="fullname") + + def get_institution(self, user): + return user.colleges[0].org.title if user.colleges else None + + class Meta: + model = User + fields = ["full_name", "total_karma", "institution"]