Newer
Older
"""
Defines the views for the API
"""
from rest_framework import viewsets
from rest_framework.views import APIView
from rest_framework.response import Response
from django.http import JsonResponse
from .pagination import PageNumberWithPageSizePagination
from .serializers import (
SmallSportListSerializer,
SportListSerializer,
CriterionListSerializer,
QuestionListSerializer,
SingleSportSerializer,
)
from .models import Sport, Criterion, Question
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):
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)
criteria = Criterion.objects.all()
is_filled_tuples = []
filled_criteria_pks = []
# TODO: Change the way that unfilled Criteria are detected (look for value -1)
# TODO: is_filled as function of sport
# 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 paginator.get_paginated_response(serializer.data)
# POST for api/admin/sport/
def create(self, request):
data_dict = SingleSportSerializer().to_internal_value(request)
print(data_dict)

borzechof99
committed
new_sport = Sport.objects.create_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):
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
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