mediacms/files/views/playlists.py
2025-10-20 11:12:56 +03:00

201 lines
8.1 KiB
Python

from django.conf import settings
from django.db.models import Q
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework import permissions, status
from rest_framework.exceptions import PermissionDenied
from rest_framework.parsers import (
FileUploadParser,
FormParser,
JSONParser,
MultiPartParser,
)
from rest_framework.response import Response
from rest_framework.settings import api_settings
from rest_framework.views import APIView
from cms.permissions import IsAuthorizedToAdd, IsUserOrEditor
from ..models import Media, Playlist, PlaylistMedia
from ..serializers import MediaSerializer, PlaylistDetailSerializer, PlaylistSerializer
class PlaylistList(APIView):
"""Playlists listings and creation views"""
permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsAuthorizedToAdd)
parser_classes = (JSONParser, MultiPartParser, FormParser, FileUploadParser)
@swagger_auto_schema(
manual_parameters=[],
tags=['Playlists'],
operation_summary='to_be_written',
operation_description='to_be_written',
responses={
200: openapi.Response('response description', PlaylistSerializer(many=True)),
},
)
def get(self, request, format=None):
pagination_class = api_settings.DEFAULT_PAGINATION_CLASS
paginator = pagination_class()
playlists = Playlist.objects.filter().prefetch_related("user")
if "author" in self.request.query_params:
author = self.request.query_params["author"].strip()
playlists = playlists.filter(user__username=author)
page = paginator.paginate_queryset(playlists, request)
serializer = PlaylistSerializer(page, many=True, context={"request": request})
return paginator.get_paginated_response(serializer.data)
@swagger_auto_schema(
manual_parameters=[],
tags=['Playlists'],
operation_summary='to_be_written',
operation_description='to_be_written',
)
def post(self, request, format=None):
serializer = PlaylistSerializer(data=request.data, context={"request": request})
if serializer.is_valid():
serializer.save(user=request.user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class PlaylistDetail(APIView):
"""Playlist related views"""
permission_classes = (permissions.IsAuthenticatedOrReadOnly, IsUserOrEditor)
parser_classes = (JSONParser, MultiPartParser, FormParser, FileUploadParser)
def get_playlist(self, friendly_token):
try:
playlist = Playlist.objects.get(friendly_token=friendly_token)
self.check_object_permissions(self.request, playlist)
return playlist
except PermissionDenied:
return Response({"detail": "not enough permissions"}, status=status.HTTP_400_BAD_REQUEST)
except BaseException:
return Response(
{"detail": "Playlist does not exist"},
status=status.HTTP_400_BAD_REQUEST,
)
@swagger_auto_schema(
manual_parameters=[],
tags=['Playlists'],
operation_summary='to_be_written',
operation_description='to_be_written',
)
def get(self, request, friendly_token, format=None):
playlist = self.get_playlist(friendly_token)
if isinstance(playlist, Response):
return playlist
serializer = PlaylistDetailSerializer(playlist, context={"request": request})
# If user is the author, show all media; otherwise, show only public and unlisted media
if request.user.is_authenticated and request.user == playlist.user:
playlist_media = PlaylistMedia.objects.filter(playlist=playlist).prefetch_related("media__user").select_related("media")
else:
playlist_media = PlaylistMedia.objects.filter(playlist=playlist).filter(Q(media__state="public") | Q(media__state="unlisted")).prefetch_related("media__user").select_related("media")
playlist_media = [c.media for c in playlist_media]
playlist_media_serializer = MediaSerializer(playlist_media, many=True, context={"request": request})
ret = serializer.data
ret["playlist_media"] = playlist_media_serializer.data
return Response(ret)
@swagger_auto_schema(
manual_parameters=[],
tags=['Playlists'],
operation_summary='to_be_written',
operation_description='to_be_written',
)
def post(self, request, friendly_token, format=None):
playlist = self.get_playlist(friendly_token)
if isinstance(playlist, Response):
return playlist
serializer = PlaylistDetailSerializer(playlist, data=request.data, context={"request": request})
if serializer.is_valid():
serializer.save(user=request.user)
return Response(serializer.data, status=status.HTTP_201_CREATED)
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
@swagger_auto_schema(
manual_parameters=[],
tags=['Playlists'],
operation_summary='to_be_written',
operation_description='to_be_written',
)
def put(self, request, friendly_token, format=None):
playlist = self.get_playlist(friendly_token)
if isinstance(playlist, Response):
return playlist
action = request.data.get("type")
media_friendly_token = request.data.get("media_friendly_token")
ordering = 0
if request.data.get("ordering"):
try:
ordering = int(request.data.get("ordering"))
except ValueError:
pass
if action in ["add", "remove", "ordering"]:
media = Media.objects.filter(friendly_token=media_friendly_token).first()
if media:
if action == "add":
media_in_playlist = PlaylistMedia.objects.filter(playlist=playlist).count()
if media_in_playlist >= settings.MAX_MEDIA_PER_PLAYLIST:
return Response(
{"detail": "max number of media for a Playlist reached"},
status=status.HTTP_400_BAD_REQUEST,
)
else:
obj, created = PlaylistMedia.objects.get_or_create(
playlist=playlist,
media=media,
ordering=media_in_playlist + 1,
)
obj.save()
return Response(
{"detail": "media added to Playlist"},
status=status.HTTP_201_CREATED,
)
elif action == "remove":
PlaylistMedia.objects.filter(playlist=playlist, media=media).delete()
return Response(
{"detail": "media removed from Playlist"},
status=status.HTTP_201_CREATED,
)
elif action == "ordering":
if ordering:
playlist.set_ordering(media, ordering)
return Response(
{"detail": "new ordering set"},
status=status.HTTP_201_CREATED,
)
else:
return Response({"detail": "media is not valid"}, status=status.HTTP_400_BAD_REQUEST)
return Response(
{"detail": "invalid or not specified action"},
status=status.HTTP_400_BAD_REQUEST,
)
@swagger_auto_schema(
manual_parameters=[],
tags=['Playlists'],
operation_summary='to_be_written',
operation_description='to_be_written',
)
def delete(self, request, friendly_token, format=None):
playlist = self.get_playlist(friendly_token)
if isinstance(playlist, Response):
return playlist
playlist.delete()
return Response(status=status.HTTP_204_NO_CONTENT)