Marietje 4.1: Addition of Django REST framework, Swagger, Dark mode and updates to Django and Bootstrap

This commit is contained in:
Lars van Rhijn
2023-09-14 19:55:51 +02:00
parent 379ababcc0
commit d1a1be7e2e
124 changed files with 4835 additions and 3490 deletions

View File

@ -0,0 +1,24 @@
from rest_framework import serializers
from marietje.api.v1.serializers import UserRelatedFieldSerializer
from songs.models import Song, ReportNote
class SongSerializer(serializers.ModelSerializer):
user = UserRelatedFieldSerializer()
class Meta:
model = Song
fields = ["id", "artist", "title", "duration", "hash", "user", "rg_gain", "rg_peak"]
class ReportNoteSerializer(serializers.ModelSerializer):
user = UserRelatedFieldSerializer(many=False, read_only=True)
class Meta:
model = ReportNote
fields = [
"song",
"note",
"user",
]

View File

@ -0,0 +1,10 @@
from django.urls import path
from .views import SongsListAPIView, SongRetrieveAPIView, SongUploadAPIView, ReportNoteCreateAPIView
urlpatterns = [
path("", SongsListAPIView.as_view(), name="song_list"),
path("<int:pk>/", SongRetrieveAPIView.as_view(), name="song_retrieve"),
path("report-notes/", ReportNoteCreateAPIView.as_view(), name="report_note_create"),
path("upload/", SongUploadAPIView.as_view(), name="song_upload"),
]

View File

@ -0,0 +1,96 @@
from rest_framework.generics import ListAPIView, RetrieveAPIView, CreateAPIView
from rest_framework import filters
from rest_framework.views import APIView
from rest_framework.response import Response
from marietje.api.permissions import IsAuthenticatedOrTokenHasScopeForMethod
from songs.api.v1.serializers import SongSerializer, ReportNoteSerializer
from songs.counters import upload_counter
from songs.models import Song
from songs.services import check_upload_stats, get_reputation, upload_file, UploadException
class SongsListAPIView(ListAPIView):
serializer_class = SongSerializer
queryset = Song.objects.all()
permission_classes = [IsAuthenticatedOrTokenHasScopeForMethod]
required_scopes_for_method = {"GET": ["read"]}
filter_backends = (filters.SearchFilter, filters.OrderingFilter)
search_fields = ["artist", "title", "user__name", "user__username"]
ordering_fields = [
"artist",
"title",
"duration",
]
class SongRetrieveAPIView(RetrieveAPIView):
serializer_class = SongSerializer
queryset = Song.objects.all()
permission_classes = [IsAuthenticatedOrTokenHasScopeForMethod]
required_scopes_for_method = {"GET": ["read"]}
class ReportNoteCreateAPIView(CreateAPIView):
serializer_class = ReportNoteSerializer
permission_classes = [IsAuthenticatedOrTokenHasScopeForMethod]
required_scopes_for_method = {"POST": ["write"]}
def perform_create(self, serializer):
serializer.save(user=self.request.user)
def create(self, request, *args, **kwargs):
if self.request.user is None:
return Response(
status=403, data={"success": False, "errorMessage": "A user is necessary for creating a report note."}
)
else:
return super(ReportNoteCreateAPIView, self).create(request, *args, **kwargs)
class SongUploadAPIView(APIView):
serializer_class = SongSerializer
permission_classes = [IsAuthenticatedOrTokenHasScopeForMethod]
required_scopes_for_method = {
"POST": ["write"],
}
def post(self, request, **kwargs):
if request.user is None:
return Response(
status=403, data={"success": False, "errorMessage": "A user is necessary for uploading a song."}
)
file = request.data.get("file", None)
artist = request.data.get("artist", None)
title = request.data.get("title", None)
if file is None:
return Response(status=400, data={"success": False, "errorMessage": "Please select a file to upload."})
if artist is None or artist == "":
return Response(status=400, data={"success": False, "errorMessage": "Please set an artist for this file."})
if title is None or title == "":
return Response(status=400, data={"success": False, "errorMessage": "Please set a title for this file."})
if not check_upload_stats(request.user):
reputation = get_reputation(request.user)
msg = (
"Queue-to-upload ratio too low. Please queue more during regular opening hours to improve the "
"ratio. (Ratio: {} ≱ 1.00)"
)
return Response(status=403, data={"success": False, "errorMessage": msg.format(reputation)})
try:
song = upload_file(file, artist, title, request.user)
upload_counter.inc()
return Response(status=200, data=self.serializer_class(song).data)
except UploadException:
return Response(
status=500,
data={
"success": False,
"errorMessage": "File could not be uploaded due to an exception that "
"occurred while contacting the file server, please try "
"again.",
},
)