Skip to content
Snippets Groups Projects
views.py 6.78 KiB
Newer Older
"""
Defines the views for the API
"""

dominip89's avatar
dominip89 committed
# from django.shortcuts import render
from rest_framework import viewsets
from rest_framework.views import APIView
from rest_framework.response import Response
borzechof99's avatar
borzechof99 committed
from django.shortcuts import get_object_or_404
from django.http import JsonResponse, HttpResponse
from .pagination import PageNumberWithPageSizePagination

from .serializers import (
    SmallSportListSerializer,
    SportListSerializer,
    CriterionListSerializer,
    QuestionListSerializer,
    CriteriaSerializer,
    IncompleteSportSerializer,
)
from .models import Sport, Criterion, Question
dominip89's avatar
dominip89 committed

# Create your views here.
dominip89's avatar
dominip89 committed
class SportListView(viewsets.ModelViewSet):  # pylint: disable=too-many-ancestors
    """
    A View returning every Sport Object
    """

    serializer_class = SportListSerializer
    queryset = Sport.objects.all()


dominip89's avatar
dominip89 committed
class CriterionListView(viewsets.ModelViewSet):  # pylint: disable=too-many-ancestors
    """
    A View returning every Criterion Object
    """

    serializer_class = CriterionListSerializer
    queryset = Criterion.objects.all()


class QuestionListView(viewsets.ModelViewSet):  # pylint: disable=too-many-ancestors
    """
    A View returning every Question Object
    """

    serializer_class = QuestionListSerializer
    queryset = Question.objects.all()


# Dev Notes:
# - If we want to include a View in the Router in urls.py, the View needs to be a Viewset
# - Those are mostly meant for Lists of Objects, so instead of get() and post(), list() and create() are used respectively
# https://stackoverflow.com/questions/30389248/how-can-i-register-a-single-view-not-a-viewset-on-my-router


class SmallSportListView(viewsets.ViewSet):
    """
    View for the List of Sports on the Sport Homepage
    TODO: More Documentation
    """

    # GET for api/admin/sport/
    def list(self, request):
        paginator = PageNumberWithPageSizePagination()
        """
        Comments on Pagination:
        Every list that needs to be paginated needs a paginator.
        Here, the Paginator object is created in the GET call.
        The Queryset which is supposed to be paginated needs to be run through the function:
        
        > new_queryset = paginator.paginate_queryset(complete_queryset, request)

        The new_queryset is a List, not a Manager, so it can be directly iterated upon.
        After the data has been worked on and run through the Serializer as normal,
        instead of returning Result(data), the paginator needs to be used again so it can add its page metadata:

        > return paginator.get_paginated_response(serializer.data)

        This function already returns a fully valid Response, so it can be directly returned.
        """

        sports = Sport.objects.all()
        sports = paginator.paginate_queryset(sports, request)
        for sport in sports:
            is_filled_tuples.append((sport, sport.is_filled()))

        serializer = SmallSportListSerializer(is_filled_tuples)

        return paginator.get_paginated_response(serializer.data)
    # POST for api/admin/sport/
    def create(self, request):

        data_dict = SingleSportSerializer().to_internal_value(request)


        new_sport.name = data_dict["name"]
        new_sport.url = data_dict["url"]

        # Before writing other Database Entries for Rating, the Sport needs to be saved once
        new_sport.save()

        for criterion, value in data_dict["criteria"]:
            new_sport.rate(criterion, value)

        new_sport.save()

        response = SingleSportSerializer(new_sport)

        return Response(response.data)

    # GET for api/admin/sport/<id>/
    def retrieve(self, request, pk=None):

borzechof99's avatar
borzechof99 committed
        sport = get_object_or_404(Sport, pk=pk)
        response = SingleSportSerializer(sport)

        return Response(response.data)

    # PUT for api/admin/sport/<id>/
    def update(self, request, pk=None):
        """
        TODO
        """

        # Get Data from Serializer
        request_data = SingleSportSerializer().to_internal_value(request)
        if request_data == None:
            # Something is Broke, so Refuse Changing Data
            return HttpResponse(status=400)

        # Get Sport from Data
        sport = Sport.objects.get(pk=pk)

        # Apply New Data to Sport
        sport.name = request_data["name"]
        sport.url = request_data["url"]

        # Overwrite Criterion Ratings
        for criterion, value in request_data["criteria"]:
            sport.rate(criterion, value)
        # Re-Serialize changed Sport and Send it back
        response = SingleSportSerializer(sport)

        return Response(response.data)

    # PATCH for api/admin/sport/<id>/
    def partial_update(self, request, pk=None):

        # Get Data from Serializer
        request_data = SingleSportSerializer().to_internal_value(request)

        if request_data == None:
            # Something is Broke, so Refuse Changing Data
            return HttpResponse(status=400)

        # Get Sport from Data
        sport = Sport.objects.get(pk=pk)

        # Apply New Data to Sport, if it exists
        if "name" in request_data.keys():
            sport.name = request_data["name"]

        if "url" in request_data.keys():
            sport.url = request_data["url"]

        # Overwrite Criterion Ratings
        for criterion, value in request_data["criteria"]:
            sport.rate(criterion, value)

        # Re-Serialize changed Sport and Send it back
        response = SingleSportSerializer(sport)

        return Response(response.data)

    # DELETE for api/admin/sport/<id>/
    def destroy(self, request, pk=None):

        sport = get_object_or_404(Sport, pk=pk)
        return HttpResponse(status=404)


class IncompleteSportView(APIView):

    authentication_classes = []

    # GET for api/admin/sport/incomplete
    def get(self, request):

        incomplete_sport_list = []

        for sport in Sport.objects.iterator():

            if not sport.is_filled():
                incomplete_sport_list.append(sport)

        response = IncompleteSportSerializer(incomplete_sport_list)

        return Response(response.data)


class CriteriaView(APIView):

    """
    View for the List of Criteria and their Metadata
    TODO: More Documentation
    """

    authentication_classes = []

    # GET for api/admin/criteria
    def get(self, request):

        data = []

        for crit in Criterion.objects.iterator():

            active_sports, sum_of_weights = crit.get_active_sum()

            data.append((crit, active_sports, sum_of_weights))

        response = CriteriaSerializer(data)

        return Response(response.data)