""" Defines the views for the API """ # from django.shortcuts import render from rest_framework import viewsets from rest_framework.views import APIView from rest_framework.response import Response from django.http import JsonResponse from .serializers import ( SmallSportListSerializer, SportListSerializer, CriterionListSerializer, QuestionListSerializer, SingleSportSerializer, ) from .models import Sport, Criterion, Question # Create your views here. class SportListView(viewsets.ModelViewSet): # pylint: disable=too-many-ancestors """ A View returning every Sport Object """ serializer_class = SportListSerializer queryset = Sport.objects.all() 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 """ authentication_classes = [] # GET for api/admin/sport/ def list(self, request): sports = Sport.objects.all() criteria = Criterion.objects.all() is_filled_tuples = [] for sport in sports.iterator(): filled_criteria_pks = [] # Get pks of Criteria which are connected to the sport for criterion in sport.criteria_ratings.iterator(): filled_criteria_pks.append(criterion.pk) is_filled = True # Check every existing criterion whether it is in the generated list for criterion in criteria.all(): if criterion.pk not in filled_criteria_pks: # A criterion isn't filled out, so stop and set to false is_filled = False break is_filled_tuples.append((sport, is_filled)) serializer = SmallSportListSerializer(is_filled_tuples) return Response(serializer.data) # POST for api/admin/sport/ def create(self, request): data_dict = SingleSportSerializer().to_internal_value(request) print(data_dict) new_sport = Sport() 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 in data_dict["criteria"]: new_sport.rate( Criterion.objects.get(pk=criterion["pk"]), 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): try: sport = Sport.objects.get(pk=pk) except: return JsonResponse( { "status_code": 404, "error": f"No Sport with ID {pk} found", }, status=404, ) return Response(SingleSportSerializer(sport).data) # PUT for api/admin/sport/<id>/ def update(self, request, pk=None): """ TODO """ data_dict = SingleSportSerializer().to_internal_value(request) sport = Sport.objects.get(pk=pk) print(data_dict) return Response({"test": "Updating a Single Entry"}) # DELETE for api/admin/sport/<id>/ def destroy(self, request, pk=None): return Response({"test": "Removing a Single Entry"}) # Dev Notes: # - This is a singular APIView which isn't meant to expose complete lists # - It cannot be written into the Router, as it isn't a Viewset, so it is written directly into the urls.py's urlspatterns like this: # path(r"api/admin/single-small-sport-list", views.SmallSportListAPIView.as_view()) # - The API isn't in the list in /api/admin because of that, but needs to be called manually here: # http://localhost:8000/api/admin/single-small-sport-list