Files
thrillwiki_django_no_react/backend/apps/api/v1/parks/views.py

117 lines
4.0 KiB
Python

"""
Park API views for ThrillWiki API v1.
"""
import logging
from django.core.exceptions import PermissionDenied
from drf_spectacular.utils import extend_schema_view, extend_schema
from drf_spectacular.types import OpenApiTypes
from rest_framework import status
from rest_framework.decorators import action
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.viewsets import ModelViewSet
from apps.parks.models import ParkPhoto
from apps.parks.services import ParkMediaService
from ..media.serializers import (
PhotoUpdateInputSerializer,
PhotoListOutputSerializer,
)
from .serializers import ParkPhotoSerializer
logger = logging.getLogger(__name__)
@extend_schema_view(
list=extend_schema(
summary="List park photos",
description="Retrieve a list of photos for a specific park.",
responses={200: PhotoListOutputSerializer(many=True)},
tags=["Parks"],
),
retrieve=extend_schema(
summary="Get park photo details",
description="Retrieve detailed information about a specific park photo.",
responses={
200: ParkPhotoSerializer,
404: OpenApiTypes.OBJECT,
},
tags=["Parks"],
),
update=extend_schema(
summary="Update park photo",
description="Update park photo information (caption, alt text, etc.)",
request=PhotoUpdateInputSerializer,
responses={
200: ParkPhotoSerializer,
400: OpenApiTypes.OBJECT,
403: OpenApiTypes.OBJECT,
404: OpenApiTypes.OBJECT,
},
tags=["Parks"],
),
destroy=extend_schema(
summary="Delete park photo",
description="Delete a park photo (only by owner or admin)",
responses={
204: None,
403: OpenApiTypes.OBJECT,
404: OpenApiTypes.OBJECT,
},
tags=["Parks"],
),
)
class ParkPhotoViewSet(ModelViewSet):
"""ViewSet for managing park photos."""
queryset = ParkPhoto.objects.select_related("park", "uploaded_by").all()
permission_classes = [IsAuthenticated]
lookup_field = "id"
def get_serializer_class(self):
"""Return appropriate serializer based on action."""
if self.action == "list":
return PhotoListOutputSerializer
elif self.action in ["update", "partial_update"]:
return PhotoUpdateInputSerializer
return ParkPhotoSerializer
def perform_update(self, serializer):
"""Update photo with permission check."""
photo = self.get_object()
if not (
self.request.user == photo.uploaded_by
or self.request.user.has_perm("parks.change_parkphoto")
):
raise PermissionDenied("You do not have permission to edit this photo.")
serializer.save()
def perform_destroy(self, instance):
"""Delete photo with permission check."""
if not (
self.request.user == instance.uploaded_by
or self.request.user.has_perm("parks.delete_parkphoto")
):
raise PermissionDenied("You do not have permission to delete this photo.")
instance.delete()
@action(detail=True, methods=["post"])
def set_primary(self, request, id=None):
"""Set this photo as the primary photo for its park."""
photo = self.get_object()
if not (
request.user == photo.uploaded_by
or request.user.has_perm("parks.change_parkphoto")
):
return Response(
{"error": "You do not have permission to edit photos for this park."},
status=status.HTTP_403_FORBIDDEN,
)
try:
ParkMediaService.set_primary_photo(photo.park, photo)
return Response({"message": "Photo set as primary successfully."})
except Exception as e:
logger.error(f"Error in set_primary_photo: {str(e)}", exc_info=True)
return Response({"error": str(e)}, status=status.HTTP_400_BAD_REQUEST)