Files
CE-Association-Website/backend/api/views/gallery.py
Amirhossein Khalili 7a8ddeabed
Some checks failed
CI/CD / Backend & Frontend Checks (push) Has been cancelled
CI/CD / Deploy to Production (push) Has been cancelled
init
2026-05-18 11:34:07 +03:30

128 lines
4.8 KiB
Python

from django.shortcuts import get_object_or_404
from django.core.files.base import ContentFile
from ninja import Router, Query, File, UploadedFile
from typing import List
import uuid
from gallery.models import Gallery
from gallery.tasks import process_uploaded_image
from api.authentication import jwt_auth
from api.schemas import GallerySchema, GalleryCreateSchema, MessageSchema, ErrorSchema
gallery_router = Router()
@gallery_router.get("/images", response=List[GallerySchema])
def list_gallery_images(
request,
page: int = Query(1, ge=1),
limit: int = Query(20, ge=1, le=50),
public_only: bool = Query(True)
):
"""List gallery images"""
queryset = Gallery.objects.select_related('uploaded_by')
if public_only:
queryset = queryset.filter(is_public=True)
# Pagination
offset = (page - 1) * limit
images = queryset[offset:offset + limit]
return images
@gallery_router.get("/images/{image_id}", response=GallerySchema)
def get_gallery_image(request, image_id: int):
"""Get single gallery image"""
image = get_object_or_404(Gallery, id=image_id, is_public=True)
return image
@gallery_router.post("/images", response={201: GallerySchema, 400: ErrorSchema}, auth=jwt_auth)
def upload_image(request, file: UploadedFile = File(...), data: GalleryCreateSchema = None):
"""Upload image to gallery (committee members only)"""
user = request.auth
if not (user.is_superuser or user.is_staff):
return 400, {"error": "Only committee members can upload images"}
# Validate file type
if not file.content_type.startswith('image/'):
return 400, {"error": "File must be an image"}
# Validate file size (10MB max)
if file.size > 10 * 1024 * 1024:
return 400, {"error": "File size must be less than 10MB"}
try:
# Create gallery item
gallery_item = Gallery.objects.create(
title=data.title if data else file.name,
description=data.description if data else "",
uploaded_by=user,
alt_text=data.alt_text if data else "",
is_public=data.is_public if data else True
)
# Save image
filename = f"gallery/{uuid.uuid4().hex}.{file.name.split('.')[-1]}"
gallery_item.image.save(filename, ContentFile(file.read()))
# Process image asynchronously
process_uploaded_image.delay(gallery_item.id)
return 201, gallery_item
except Exception as e:
return 400, {"error": "Failed to upload image", "details": str(e)}
@gallery_router.put("/images/{image_id}", response={200: GallerySchema, 400: ErrorSchema}, auth=jwt_auth)
def update_image(request, image_id: int, data: GalleryCreateSchema):
"""Update gallery image metadata"""
user = request.auth
image = get_object_or_404(Gallery, id=image_id)
if not (image.uploaded_by == user or user.is_superuser or user.is_staff):
return 400, {"error": "You can only edit your own images"}
try:
for field, value in data.dict(exclude_unset=True).items():
setattr(image, field, value)
image.save()
return 200, image
except Exception as e:
return 400, {"error": "Failed to update image", "details": str(e)}
@gallery_router.delete("/images/{image_id}", response={200: MessageSchema, 400: ErrorSchema}, auth=jwt_auth)
def delete_image(request, image_id: int):
"""Soft delete a gallery image owned by the requester or committee."""
user = request.auth
image = get_object_or_404(Gallery, id=image_id)
if not (image.uploaded_by == user or user.is_superuser or user.is_staff):
return 400, {"error": "You can only delete your own images"}
image.delete()
return 200, {"message": "Image deleted successfully"}
@gallery_router.get("/deleted/images", response=List[GallerySchema], auth=jwt_auth)
def list_deleted_gallery_images(request):
"""List all soft-deleted gallery images (Admin/Committee only)"""
if not (request.auth.is_staff or request.auth.is_superuser):
return 403, {"error": "Permission denied"}
return Gallery.deleted_objects.all().select_related('uploaded_by')
@gallery_router.post("/deleted/images/{image_id}/restore", response={200: MessageSchema, 400: ErrorSchema}, auth=jwt_auth)
def restore_gallery_image(request, image_id: int):
"""Restore a soft-deleted gallery image (Admin/Committee only)"""
if not (request.auth.is_staff or request.auth.is_superuser):
return 403, {"error": "Permission denied"}
try:
image = Gallery.deleted_objects.get(id=image_id)
image.restore()
return 200, {"message": f"Gallery image '{image.title}' restored successfully."}
except Gallery.DoesNotExist:
return 400, {"error": "Gallery image not found or not soft-deleted."}