Files
decomp.me/backend/coreapp/views/user.py
Mark Street a5e77271b2 Allow filtering of user's scratches based on platform, preset or comp… (#1720)
Allow filtering of user's scratches based on platform, preset or compiler
2025-11-02 17:48:02 +00:00

108 lines
3.2 KiB
Python

import django_filters
from django.contrib.auth import logout
from django.db.models.query import QuerySet
from django.shortcuts import get_object_or_404
from django.utils.decorators import method_decorator
from rest_framework import generics, filters
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.views import APIView
from ..decorators.cache import globally_cacheable
from ..filters.search import NonEmptySearchFilter
from ..middleware import Request
from ..models.github import GitHubUser
from ..models.profile import Profile
from ..models.scratch import Scratch
from ..serializers import TerseScratchSerializer, serialize_profile
from .scratch import ScratchPagination, ScratchViewSet
class CurrentUser(APIView):
"""
View to access the current user profile.
"""
def get(self, request: Request) -> Response:
user = serialize_profile(request.profile)
return Response(user)
def post(self, request: Request) -> Response:
"""
Login if the 'code' parameter is provided. Log out otherwise.
"""
if "code" in request.data:
GitHubUser.login(request, request.data["code"])
assert not request.profile.is_anonymous()
return self.get(request)
else:
logout(request)
profile = Profile()
profile.save()
request.profile = profile
request.session["profile_id"] = request.profile.id
return self.get(request)
class CurrentUserScratchList(generics.ListAPIView): # type: ignore
"""
Gets the current user's scratches
"""
pagination_class = ScratchPagination
serializer_class = TerseScratchSerializer
filterset_fields = ["platform", "compiler", "preset"]
filter_backends = [
django_filters.rest_framework.DjangoFilterBackend,
NonEmptySearchFilter,
filters.OrderingFilter,
]
ordering_fields = ["creation_time", "last_updated", "score", "match_percent"]
def get_queryset(self) -> QuerySet[Scratch]:
if self.request.profile.id is None:
return Scratch.objects.none()
return ScratchViewSet.queryset.filter(owner__id=self.request.profile.id)
@method_decorator(
globally_cacheable(max_age=60, stale_while_revalidate=30), name="dispatch"
)
class UserScratchList(generics.ListAPIView): # type: ignore
"""
Gets a user's scratches
"""
pagination_class = ScratchPagination
serializer_class = TerseScratchSerializer
filterset_fields = ["platform", "compiler", "preset"]
filter_backends = [
django_filters.rest_framework.DjangoFilterBackend,
NonEmptySearchFilter,
filters.OrderingFilter,
]
ordering_fields = ["creation_time", "last_updated", "score", "match_percent"]
def get_queryset(self) -> QuerySet[Scratch]:
return ScratchViewSet.queryset.filter(
owner__user__username=self.kwargs["username"]
)
@api_view(["GET"]) # type: ignore
@globally_cacheable(max_age=300, stale_while_revalidate=30)
def user(request: Request, username: str) -> Response:
"""
Gets a user's basic data
"""
return Response(
serialize_profile(get_object_or_404(Profile, user__username=username))
)