initial API views

This commit is contained in:
2025-05-20 19:08:07 +02:00
parent 5a432ae1ef
commit 8b2bbfd4d3
9 changed files with 108 additions and 9 deletions
+2
View File
@@ -0,0 +1,2 @@
from .track import TrackSerializer
from .artist import ArtistSerializer
+10
View File
@@ -0,0 +1,10 @@
from playlist.models import Artist
from rest_framework import serializers
class ArtistSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Artist
fields = ['id', 'name', 'url']
extra_kwargs = {
'url': {'view_name': 'api-artist', 'lookup_field': 'id'},
}
+11
View File
@@ -0,0 +1,11 @@
from playlist.models import Track
from rest_framework import serializers
class TrackSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Track
fields = ['url', 'id', 'name', 'artists', 'nominated_by', 'explicit', 'duration_ms', 'popularity', 'banter', 'banter_done', 'old']
extra_kwargs = {
'url': {'view_name': 'api-track', 'lookup_field': 'id'},
'artists': {'view_name': 'api-artist', 'lookup_field': 'id'}
}
+5
View File
@@ -4,6 +4,11 @@ from django.conf import settings
from django.conf.urls.static import static from django.conf.urls.static import static
urlpatterns = [ urlpatterns = [
path('api/', views.api_root, name="api-root"),
path('api/track', views.TrackListView.as_view(), name="api-tracks"),
path('api/track/<id>', views.TrackDetailView.as_view(), name="api-track"),
path('api/artist/<id>', views.ArtistDetailView.as_view(), name="api-artist"),
path('api/artist', views.ArtistListView.as_view(), name="api-artists"),
path('track/', views.NominateView.as_view(), name="nominate"), path('track/', views.NominateView.as_view(), name="nominate"),
path('vote/', views.VoteView.as_view(), name="vote"), path('vote/', views.VoteView.as_view(), name="vote"),
path('vote/undo', views.UndoView.as_view(), name="undo"), path('vote/undo', views.UndoView.as_view(), name="undo"),
+4
View File
@@ -0,0 +1,4 @@
from .static import *
from .api.track import *
from .api.artist import *
from .api.root import *
+22
View File
@@ -0,0 +1,22 @@
from itertools import permutations
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.authentication import SessionAuthentication
from rest_framework.permissions import IsAuthenticated
from playlist.models import Artist
from playlist.serializers import ArtistSerializer
class ArtistListView(APIView):
authentication_classes = [SessionAuthentication]
permission_classes = [IsAuthenticated]
def get(self, request):
artists = Artist.objects.all()
serializer = ArtistSerializer(artists, many=True, context={'request': request})
return Response(serializer.data)
class ArtistDetailView(APIView):
def get(self, request, id):
artist = Artist.objects.get(pk=id)
serializer = ArtistSerializer(artist, context={'request': request})
return Response(serializer.data)
+11
View File
@@ -0,0 +1,11 @@
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
@api_view(['GET'])
def api_root(request, format=None):
return Response({
'tracks': reverse('api-tracks', request=request, format=format),
'artists': reverse('api-artists', request=request, format=format)
})
+34
View File
@@ -0,0 +1,34 @@
from rest_framework import viewsets
from rest_framework.views import APIView
from rest_framework.response import Response
from playlist.models import Track
from playlist.serializers import TrackSerializer
class TrackViewSet(viewsets.ModelViewSet):
queryset = Track.objects.all()
serializer_class = TrackSerializer
class TrackListView(APIView):
def get(self, request):
tracks = Track.objects.all()
serializer = TrackSerializer(tracks, many=True, context={'request': request})
return Response(serializer.data)
class TrackDetailView(APIView):
def get(self, request, id):
track = Track.objects.get(pk=id)
serializer = TrackSerializer(track, context={'request': request})
return Response(serializer.data)
def put(self, request, id):
track = Track.objects.get(pk=id)
serializer = TrackSerializer(track, data=request.data, context={'request': request})
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=400)
def post(self, request):
serializer = TrackSerializer(data=request.data, context={'request': request})
if serializer.is_valid():
serializer.save()
return Response(serializer.data)
return Response(serializer.errors, status=400)
@@ -10,10 +10,10 @@ import os
from datetime import UTC, datetime from datetime import UTC, datetime
from collections import OrderedDict from collections import OrderedDict
from dotenv import load_dotenv from dotenv import load_dotenv
from .models import Track, Artist, Album, Vote, Background, Profile, Playlist from ..models import Track, Artist, Album, Vote, Background, Profile, Playlist
from .utils import track_from_json, get_unvoted, get_unvoted_count from ..utils import track_from_json, get_unvoted, get_unvoted_count
from .spotify import spt from ..spotify import spt
from .tasks import get_banter, get_and_dither_image from ..tasks import get_banter, get_and_dither_image
load_dotenv() load_dotenv()
@@ -90,7 +90,7 @@ class NominateView(LoginRequiredMixin, View):
get_banter.delay(track.id) get_banter.delay(track.id)
return TemplateResponse(request, "Nominate.html", { return TemplateResponse(request, "Nominate.html", {
"message_type": "warning", "message_type": "warning",
"message": f"Hey een klassieker, die stond al in {track.from_playlist}. Geen probleem, we proberen hem nog een keer dit jaar!", "message": f"Hey een klassieker, die stond al in {track.from_playlist}. Geen probleem, we proberen hem nog een keer dit jaar!",
"message_title": str(track) "message_title": str(track)
}) })
return TemplateResponse(request, "Nominate.html", { return TemplateResponse(request, "Nominate.html", {
@@ -119,7 +119,7 @@ class NominateView(LoginRequiredMixin, View):
get_banter.delay(track.id) get_banter.delay(track.id)
profile.quota -= 1 profile.quota -= 1
profile.save() profile.save()
return TemplateResponse(request, "Nominate.html", {"message_type": "nominated", "message_title": str(track), "message": "Genomineerd!"}) return TemplateResponse(request, "Nominate.html", {"message_type": "nominated", "message_title": str(track), "message": "Genomineerd!"})
class SettingsView(LoginRequiredMixin, View): class SettingsView(LoginRequiredMixin, View):
@@ -153,7 +153,7 @@ class SettingsView(LoginRequiredMixin, View):
pass pass
finally: finally:
return self.get(request) return self.get(request)
class UndoView(LoginRequiredMixin, View): class UndoView(LoginRequiredMixin, View):
def get(self, request): def get(self, request):
return HttpResponseRedirect('/vote/') return HttpResponseRedirect('/vote/')
@@ -208,7 +208,7 @@ class OverView(LoginRequiredMixin, View):
artists[artist.name][vote.track.album.name] = [] artists[artist.name][vote.track.album.name] = []
artists[artist.name][vote.track.album.name] += [vote.track] artists[artist.name][vote.track.album.name] += [vote.track]
artists_ordered = OrderedDict(sorted(artists.items())) artists_ordered = OrderedDict(sorted(artists.items()))
context = { context = {
"artists": artists_ordered "artists": artists_ordered
} }
@@ -293,7 +293,7 @@ class PlaylistImportView(LoginRequiredMixin, View):
print(e) print(e)
return self.get(request) return self.get(request)
class StroopwafelView(View): class StroopwafelView(View):
def get(self, request): def get(self, request):
nominated_count = Track.objects.all().count() nominated_count = Track.objects.all().count()