You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
7.4 KiB
187 lines
7.4 KiB
from django.db import transaction
|
|
from django.db.models import Q
|
|
from rest_framework import status
|
|
from rest_framework.authentication import TokenAuthentication
|
|
from rest_framework.decorators import action
|
|
from rest_framework.parsers import FormParser, JSONParser, MultiPartParser
|
|
from rest_framework.permissions import IsAuthenticated
|
|
from rest_framework.response import Response
|
|
from rest_framework.viewsets import ModelViewSet, ReadOnlyModelViewSet
|
|
|
|
from apps.account.permissions import IsSuperAdmin
|
|
from utils.pagination import StandardResultsSetPagination
|
|
|
|
from .models import PlaylistItem, Video, VideoCategory, VideoCollection, VideoPlaylist
|
|
from .serializers_admin import (
|
|
AdminVideoCategorySerializer,
|
|
AdminVideoCollectionSerializer,
|
|
AdminVideoDetailSerializer,
|
|
AdminVideoListSerializer,
|
|
AdminVideoPlaylistDetailSerializer,
|
|
AdminVideoPlaylistItemSerializer,
|
|
AdminVideoPlaylistListSerializer,
|
|
)
|
|
|
|
|
|
class AdminVideoCategoryViewSet(ReadOnlyModelViewSet):
|
|
serializer_class = AdminVideoCategorySerializer
|
|
permission_classes = [IsAuthenticated, IsSuperAdmin]
|
|
authentication_classes = [TokenAuthentication]
|
|
pagination_class = None
|
|
|
|
def get_queryset(self):
|
|
return VideoCategory.objects.all().order_by("title")
|
|
|
|
|
|
class AdminVideoCollectionViewSet(ReadOnlyModelViewSet):
|
|
serializer_class = AdminVideoCollectionSerializer
|
|
permission_classes = [IsAuthenticated, IsSuperAdmin]
|
|
authentication_classes = [TokenAuthentication]
|
|
pagination_class = None
|
|
|
|
def get_queryset(self):
|
|
return VideoCollection.objects.all().order_by("display_position", "order", "title")
|
|
|
|
|
|
class AdminVideoViewSet(ModelViewSet):
|
|
permission_classes = [IsAuthenticated, IsSuperAdmin]
|
|
authentication_classes = [TokenAuthentication]
|
|
pagination_class = StandardResultsSetPagination
|
|
parser_classes = (MultiPartParser, FormParser, JSONParser)
|
|
|
|
def get_serializer_class(self):
|
|
if self.action == "list":
|
|
return AdminVideoListSerializer
|
|
return AdminVideoDetailSerializer
|
|
|
|
def get_queryset(self):
|
|
queryset = Video.objects.all()
|
|
|
|
search_query = self.request.query_params.get("search")
|
|
if search_query:
|
|
queryset = queryset.filter(
|
|
Q(title__icontains=search_query)
|
|
| Q(slug__icontains=search_query)
|
|
| Q(description__icontains=search_query)
|
|
| Q(video_url__icontains=search_query)
|
|
)
|
|
|
|
status_filter = self.request.query_params.get("status")
|
|
if status_filter in {"true", "false"}:
|
|
queryset = queryset.filter(status=status_filter == "true")
|
|
|
|
video_type = self.request.query_params.get("video_type")
|
|
if video_type and video_type != "all":
|
|
queryset = queryset.filter(video_type=video_type)
|
|
|
|
return queryset.order_by("-created_at")
|
|
|
|
|
|
class AdminVideoPlaylistViewSet(ModelViewSet):
|
|
permission_classes = [IsAuthenticated, IsSuperAdmin]
|
|
authentication_classes = [TokenAuthentication]
|
|
pagination_class = StandardResultsSetPagination
|
|
parser_classes = (MultiPartParser, FormParser, JSONParser)
|
|
|
|
def get_serializer_class(self):
|
|
if self.action == "list":
|
|
return AdminVideoPlaylistListSerializer
|
|
return AdminVideoPlaylistDetailSerializer
|
|
|
|
def get_queryset(self):
|
|
queryset = VideoPlaylist.objects.all().prefetch_related("categories", "collections", "playlist_items__video")
|
|
|
|
search_query = self.request.query_params.get("search")
|
|
if search_query:
|
|
queryset = queryset.filter(
|
|
Q(title__icontains=search_query)
|
|
| Q(slug__icontains=search_query)
|
|
| Q(slogan__icontains=search_query)
|
|
| Q(description__icontains=search_query)
|
|
)
|
|
|
|
status_filter = self.request.query_params.get("status")
|
|
if status_filter in {"true", "false"}:
|
|
queryset = queryset.filter(status=status_filter == "true")
|
|
|
|
category_id = self.request.query_params.get("category")
|
|
if category_id and category_id != "all":
|
|
queryset = queryset.filter(categories__id=category_id)
|
|
|
|
collection_id = self.request.query_params.get("collection")
|
|
if collection_id and collection_id != "all":
|
|
queryset = queryset.filter(collections__id=collection_id)
|
|
|
|
return queryset.distinct().order_by("order", "-created_at")
|
|
|
|
@action(detail=True, methods=["get", "post"], url_path="items")
|
|
def items(self, request, pk=None):
|
|
playlist = self.get_object()
|
|
|
|
if request.method.lower() == "get":
|
|
items = playlist.playlist_items.select_related("video").order_by("priority", "id")
|
|
serializer = AdminVideoPlaylistItemSerializer(items, many=True, context={"request": request})
|
|
return Response(serializer.data)
|
|
|
|
serializer = AdminVideoPlaylistItemSerializer(
|
|
data={
|
|
**request.data,
|
|
"playlist": playlist.id,
|
|
"priority": request.data.get("priority", playlist.playlist_items.count() + 1),
|
|
},
|
|
context={"request": request},
|
|
)
|
|
serializer.is_valid(raise_exception=True)
|
|
serializer.save()
|
|
playlist.total_time = playlist.calculate_total_time()
|
|
playlist.save(update_fields=["total_time"])
|
|
return Response(serializer.data, status=status.HTTP_201_CREATED)
|
|
|
|
@action(detail=True, methods=["patch", "delete"], url_path=r"items/(?P<item_id>\d+)")
|
|
def item_detail(self, request, pk=None, item_id=None):
|
|
playlist = self.get_object()
|
|
item = playlist.playlist_items.select_related("video").get(pk=item_id)
|
|
|
|
if request.method.lower() == "delete":
|
|
item.delete()
|
|
playlist.total_time = playlist.calculate_total_time()
|
|
playlist.save(update_fields=["total_time"])
|
|
return Response(status=status.HTTP_204_NO_CONTENT)
|
|
|
|
serializer = AdminVideoPlaylistItemSerializer(
|
|
item,
|
|
data={**request.data, "playlist": playlist.id},
|
|
partial=True,
|
|
context={"request": request},
|
|
)
|
|
serializer.is_valid(raise_exception=True)
|
|
serializer.save()
|
|
playlist.total_time = playlist.calculate_total_time()
|
|
playlist.save(update_fields=["total_time"])
|
|
return Response(serializer.data)
|
|
|
|
@action(detail=True, methods=["post"], url_path="items/reorder")
|
|
def reorder_items(self, request, pk=None):
|
|
playlist = self.get_object()
|
|
item_ids = request.data.get("item_ids", [])
|
|
if not isinstance(item_ids, list):
|
|
return Response({"detail": "item_ids must be a list."}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
items = list(playlist.playlist_items.filter(id__in=item_ids))
|
|
if len(items) != len(item_ids):
|
|
return Response({"detail": "Some items were not found."}, status=status.HTTP_400_BAD_REQUEST)
|
|
|
|
item_map = {item.id: item for item in items}
|
|
with transaction.atomic():
|
|
for index, item_id in enumerate(item_ids, start=1):
|
|
item = item_map[item_id]
|
|
if item.priority != index:
|
|
item.priority = index
|
|
item.save(update_fields=["priority"])
|
|
|
|
serializer = AdminVideoPlaylistItemSerializer(
|
|
playlist.playlist_items.select_related("video").order_by("priority", "id"),
|
|
many=True,
|
|
context={"request": request},
|
|
)
|
|
return Response(serializer.data)
|