winofy-backend/apps/core/views/media.py
2026-08-18 13:58:54 +03:30

51 lines
2 KiB
Python

import uuid
from datetime import timedelta
from django.conf import settings
from drf_spectacular.utils import extend_schema
from rest_framework import status
from rest_framework.response import Response
from rest_framework.views import APIView
from apps.core.serializers import MediaPresignInputSerializer, MediaPresignOutputSerializer
from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements
from utils.clients.minio_client import minio_client
from utils.exceptions import ServiceUnavailable
class MediaPresignView(APIView):
"""Presigned MinIO upload URL for product/store images (icon, logo, cover, ...).
The client uploads the file bytes directly to MinIO with the returned
upload_url, then submits the returned object_key as the field value when
creating/updating the owning resource (e.g. Store.logo, Product.image).
"""
schema_tags = ['Media']
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
required_alternate_scopes = {
"POST": [[]],
}
@extend_schema(request=MediaPresignInputSerializer, responses={201: MediaPresignOutputSerializer})
def post(self, request):
serializer = MediaPresignInputSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
filename = serializer.validated_data['filename']
extension = filename.rsplit('.', 1)[-1] if '.' in filename else 'bin'
object_key = f'uploads/{uuid.uuid4()}.{extension}'
try:
upload_url = minio_client.presigned_put_object(
settings.MINIO_BUCKET_NAME,
object_key,
expires=timedelta(minutes=30),
)
except Exception:
raise ServiceUnavailable('خطا در دریافت لینک آپلود. لطفاً دوباره تلاش کنید.')
return Response(
MediaPresignOutputSerializer({'upload_url': upload_url, 'object_key': object_key}).data,
status=status.HTTP_201_CREATED,
)