mirror of
https://github.com/pacnpal/thrillwiki_django_no_react.git
synced 2025-12-20 07:11:08 -05:00
- Created ParkPhoto and ParkPhotoEvent models in the parks app, including fields for image, caption, alt text, and relationships to the Park model. - Implemented triggers for insert and update operations on ParkPhoto to log changes in ParkPhotoEvent. - Created RidePhoto and RidePhotoEvent models in the rides app, with similar structure and functionality as ParkPhoto. - Added fields for photo type in RidePhoto and implemented corresponding triggers for logging changes. - Established necessary indexes and unique constraints for both models to ensure data integrity and optimize queries.
118 lines
4.0 KiB
Python
118 lines
4.0 KiB
Python
"""
|
|
Ride 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.rides.models import RidePhoto
|
|
from apps.rides.services import RideMediaService
|
|
from ..media.serializers import (
|
|
PhotoUpdateInputSerializer,
|
|
PhotoListOutputSerializer,
|
|
)
|
|
from .serializers import RidePhotoSerializer
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
@extend_schema_view(
|
|
list=extend_schema(
|
|
summary="List ride photos",
|
|
description="Retrieve a list of photos for a specific ride.",
|
|
responses={200: PhotoListOutputSerializer(many=True)},
|
|
tags=["Rides"],
|
|
),
|
|
retrieve=extend_schema(
|
|
summary="Get ride photo details",
|
|
description="Retrieve detailed information about a specific ride photo.",
|
|
responses={
|
|
200: RidePhotoSerializer,
|
|
404: OpenApiTypes.OBJECT,
|
|
},
|
|
tags=["Rides"],
|
|
),
|
|
update=extend_schema(
|
|
summary="Update ride photo",
|
|
description="Update ride photo information (caption, alt text, etc.)",
|
|
request=PhotoUpdateInputSerializer,
|
|
responses={
|
|
200: RidePhotoSerializer,
|
|
400: OpenApiTypes.OBJECT,
|
|
403: OpenApiTypes.OBJECT,
|
|
404: OpenApiTypes.OBJECT,
|
|
},
|
|
tags=["Rides"],
|
|
),
|
|
destroy=extend_schema(
|
|
summary="Delete ride photo",
|
|
description="Delete a ride photo (only by owner or admin)",
|
|
responses={
|
|
204: None,
|
|
403: OpenApiTypes.OBJECT,
|
|
404: OpenApiTypes.OBJECT,
|
|
},
|
|
tags=["Rides"],
|
|
),
|
|
)
|
|
class RidePhotoViewSet(ModelViewSet):
|
|
"""ViewSet for managing ride photos."""
|
|
|
|
queryset = RidePhoto.objects.select_related("ride", "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 RidePhotoSerializer
|
|
|
|
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("rides.change_ridephoto")
|
|
):
|
|
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("rides.delete_ridephoto")
|
|
):
|
|
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 ride."""
|
|
photo = self.get_object()
|
|
if not (
|
|
request.user == photo.uploaded_by
|
|
or request.user.has_perm("rides.change_ridephoto")
|
|
):
|
|
return Response(
|
|
{"error": "You do not have permission to edit photos for this ride."},
|
|
status=status.HTTP_403_FORBIDDEN,
|
|
)
|
|
try:
|
|
RideMediaService.set_primary_photo(photo.ride, 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)
|