Skip to content
Snippets Groups Projects
views.py 7.26 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
borzechof99's avatar
borzechof99 committed
from django.http import 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):
    """
borzechof99's avatar
borzechof99 committed
    View for Sports and List of Sport:
    List returns every Sport with the is_filled Field
    Detail returns single Sports with every Criterium
    # GET for api/admin/sport/
    def list(self, request):
borzechof99's avatar
borzechof99 committed
        GET for api/admin/sport/
        Returns a List of Every Sport with the is_filled Field, stating whether every Criterion is given a Rating or not
borzechof99's avatar
borzechof99 committed
        paginator = PageNumberWithPageSizePagination()

        sports = Sport.objects.all().order_by("name")
        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):
borzechof99's avatar
borzechof99 committed
        """
        POST for api/admin/sport/
        View for Creating a New Sport
        """
borzechof99's avatar
borzechof99 committed
        request_data = SingleSportSerializer().to_internal_value(request)
borzechof99's avatar
borzechof99 committed
        if request_data is None:
borzechof99's avatar
borzechof99 committed
        new_sport.name = request_data["name"]
        new_sport.url = request_data["url"]

        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
        """
        GET for api/admin/sport/<pk>/
        View for getting a Single Sport, with the pk to the Sport being the argument in the URL
        """
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):
        """
borzechof99's avatar
borzechof99 committed
        PUT for api/admin/sport/<id>/
        Creates a Sport if it doesn't exist, otherwise overwrites it.
        TODO: Maybe Rework PUT if needed of Admin Frontend
        # Get Data from Serializer
        request_data = SingleSportSerializer().to_internal_value(request)
borzechof99's avatar
borzechof99 committed
        if request_data is 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):
borzechof99's avatar
borzechof99 committed
        """
        PATCH for api/admin/sport/<id>/
        Fills in the given Values into the Sport specified in the URL
        """

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

borzechof99's avatar
borzechof99 committed
        if request_data is 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):
borzechof99's avatar
borzechof99 committed
        """
        DELETE for api/admin/sport/<id>/
        Removes Sport Object specified in the URL
        """
        sport = get_object_or_404(Sport, pk=pk)
        return HttpResponse(status=404)


class IncompleteSportView(APIView):
borzechof99's avatar
borzechof99 committed
    """
    Returns all Sport Objects with Incomplete Ratings
    """
borzechof99's avatar
borzechof99 committed
    # GET for api/admin/sport/incomplete/
borzechof99's avatar
borzechof99 committed
        """
        GET for api/admin/sport/incomplete/
        Returns every incomplete Sport with its incomplete Ratings in a paginated manner
borzechof99's avatar
borzechof99 committed
        """
        paginator = PageNumberWithPageSizePagination()
        queryset = Sport.objects.iterator()
        queryset = paginator.paginate_queryset(queryset, request)

        for sport in queryset:

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

        response = IncompleteSportSerializer(incomplete_sport_list)

        return paginator.get_paginated_response(response.data)


class CriteriaView(APIView):
    """
    View for the List of Criteria and their Metadata
    """

    authentication_classes = []

borzechof99's avatar
borzechof99 committed
    # GET for api/admin/criteria/
borzechof99's avatar
borzechof99 committed
        """
        GET for api/admin/criteria/
        Returns every Criterium and the Metadata of
        Number of Sports in which the Rating is >1
        and the cumulated sum of Ratings >1
        TODO: Also Pagination
borzechof99's avatar
borzechof99 committed
        """

        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)