from django.core.cache import cache from django.db.models import Avg, Count from django.db.models.functions import Round from comment.models import Comment from problem.models import Problem from utils.api import APIView from utils.constants import CacheKey from account.decorators import login_required from utils.api.api import validate_serializer from comment.serializers import CreateCommentSerializer, CommentSerializer from submission.models import Submission, JudgeStatus class CommentAPI(APIView): @validate_serializer(CreateCommentSerializer) @login_required def post(self, request): data = request.data try: problem = Problem.objects.get(id=data["problem_id"], visible=True) except Problem.DoesNotExist: self.error("problem is not exists") try: submission = ( Submission.objects.select_related("problem") .filter( user_id=request.user.id, problem_id=data["problem_id"], result=JudgeStatus.ACCEPTED, ) .first() ) except Submission.DoesNotExist: self.error("submission is not exists or not accepted") language = submission.language if language == "Python3": language = "Python" Comment.objects.create( user=request.user, problem=problem, submission=submission, language=language, description_rating=data["description_rating"], difficulty_rating=data["difficulty_rating"], comprehensive_rating=data["comprehensive_rating"], content=data["content"], ) cache.delete(f"{CacheKey.comment_stats}:{problem.id}") return self.success() @login_required def get(self, request): problem_id = request.GET.get("problem_id") comment = ( Comment.objects.select_related("problem") .filter(user=request.user, problem_id=problem_id) .first() ) if comment: return self.success(CommentSerializer(comment).data) else: return self.success() class CommentStatisticsAPI(APIView): def get(self, request): problem_id = request.GET.get("problem_id") cache_key = f"{CacheKey.comment_stats}:{problem_id}" cached = cache.get(cache_key) if cached is not None: return self.success(cached) agg = Comment.objects.filter(problem_id=problem_id).aggregate( count=Count("id"), description=Round(Avg("description_rating"), 2), difficulty=Round(Avg("difficulty_rating"), 2), comprehensive=Round(Avg("comprehensive_rating"), 2), ) if not agg["count"]: return self.success() data = {"count": agg["count"], "rating": { "description": agg["description"], "difficulty": agg["difficulty"], "comprehensive": agg["comprehensive"], }} cache.set(cache_key, data, 3600) return self.success(data)