Clean up accumulated backward-compat shims, deprecated wrappers, unused aliases, and legacy code across the codebase. Since the platform is not live yet, this establishes a clean baseline. Changes: - Delete deprecated middleware/context.py (RequestContext, get_request_context) - Remove unused factory get_store_email_settings_service() - Remove deprecated pagination_full macro, /admin/platform-homepage route - Remove ConversationResponse, InvoiceSettings* unprefixed aliases - Simplify celery_config.py (remove empty LEGACY_TASK_MODULES) - Standardize billing exceptions: *Error aliases → *Exception names - Consolidate duplicate TierNotFoundError/FeatureNotFoundError classes - Remove deprecated is_admin_request() from Store/PlatformContextManager - Remove is_platform_default field, MediaUploadResponse legacy flat fields - Remove MediaItemResponse.url alias, update JS to use file_url - Update all affected tests and documentation Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
185 lines
5.2 KiB
Python
185 lines
5.2 KiB
Python
# app/modules/cms/schemas/media.py
|
|
"""
|
|
Media/file management Pydantic schemas for API validation and responses.
|
|
|
|
This module provides schemas for:
|
|
- Media library listing
|
|
- File upload responses
|
|
- Media metadata operations
|
|
- Media usage tracking
|
|
"""
|
|
|
|
from datetime import datetime
|
|
from typing import Any
|
|
|
|
from pydantic import BaseModel, Field
|
|
|
|
# ============================================================================
|
|
# SHARED RESPONSE SCHEMAS
|
|
# ============================================================================
|
|
|
|
|
|
class MessageResponse(BaseModel):
|
|
"""Generic message response for simple operations."""
|
|
|
|
message: str
|
|
|
|
|
|
# ============================================================================
|
|
# MEDIA ITEM SCHEMAS
|
|
# ============================================================================
|
|
|
|
|
|
class MediaItemResponse(BaseModel):
|
|
"""Single media item response."""
|
|
|
|
id: int
|
|
filename: str
|
|
original_filename: str | None = None
|
|
file_url: str
|
|
thumbnail_url: str | None = None
|
|
media_type: str # image, video, document
|
|
mime_type: str | None = None
|
|
file_size: int | None = None # bytes
|
|
width: int | None = None # for images/videos
|
|
height: int | None = None # for images/videos
|
|
alt_text: str | None = None
|
|
description: str | None = None
|
|
folder: str | None = None
|
|
extra_metadata: dict[str, Any] | None = None
|
|
created_at: datetime
|
|
updated_at: datetime | None = None
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
class MediaListResponse(BaseModel):
|
|
"""Paginated list of media items."""
|
|
|
|
media: list[MediaItemResponse] = []
|
|
total: int = 0
|
|
skip: int = 0
|
|
limit: int = 100
|
|
message: str | None = None
|
|
|
|
|
|
# ============================================================================
|
|
# UPLOAD RESPONSE SCHEMAS
|
|
# ============================================================================
|
|
|
|
|
|
class MediaUploadResponse(BaseModel):
|
|
"""Response for single file upload."""
|
|
|
|
success: bool = True
|
|
message: str | None = None
|
|
media: MediaItemResponse | None = None
|
|
|
|
|
|
class UploadedFileInfo(BaseModel):
|
|
"""Information about a successfully uploaded file."""
|
|
|
|
id: int
|
|
filename: str
|
|
file_url: str
|
|
thumbnail_url: str | None = None
|
|
|
|
|
|
class FailedFileInfo(BaseModel):
|
|
"""Information about a failed file upload."""
|
|
|
|
filename: str
|
|
error: str
|
|
|
|
|
|
class MultipleUploadResponse(BaseModel):
|
|
"""Response for multiple file upload."""
|
|
|
|
uploaded_files: list[UploadedFileInfo] = []
|
|
failed_files: list[FailedFileInfo] = []
|
|
total_uploaded: int = 0
|
|
total_failed: int = 0
|
|
message: str | None = None
|
|
|
|
|
|
# ============================================================================
|
|
# MEDIA DETAIL SCHEMAS
|
|
# ============================================================================
|
|
|
|
|
|
class MediaDetailResponse(BaseModel):
|
|
"""Detailed media item response with usage info."""
|
|
|
|
id: int | None = None
|
|
filename: str | None = None
|
|
original_filename: str | None = None
|
|
file_url: str | None = None
|
|
thumbnail_url: str | None = None
|
|
media_type: str | None = None
|
|
mime_type: str | None = None
|
|
file_size: int | None = None
|
|
width: int | None = None
|
|
height: int | None = None
|
|
alt_text: str | None = None
|
|
description: str | None = None
|
|
folder: str | None = None
|
|
extra_metadata: dict[str, Any] | None = None
|
|
created_at: datetime | None = None
|
|
updated_at: datetime | None = None
|
|
message: str | None = None
|
|
|
|
model_config = {"from_attributes": True}
|
|
|
|
|
|
# ============================================================================
|
|
# MEDIA UPDATE SCHEMAS
|
|
# ============================================================================
|
|
|
|
|
|
class MediaMetadataUpdate(BaseModel):
|
|
"""Request model for updating media metadata."""
|
|
|
|
filename: str | None = Field(None, max_length=255)
|
|
alt_text: str | None = Field(None, max_length=500)
|
|
description: str | None = None
|
|
folder: str | None = Field(None, max_length=100)
|
|
metadata: dict[str, Any] | None = None # Named 'metadata' in API, stored as 'extra_metadata'
|
|
|
|
|
|
# ============================================================================
|
|
# MEDIA USAGE SCHEMAS
|
|
# ============================================================================
|
|
|
|
|
|
class MediaUsageItem(BaseModel):
|
|
"""Information about an entity using this media."""
|
|
|
|
entity_type: str # Defined by provider (e.g. "product")
|
|
entity_id: int
|
|
entity_name: str
|
|
usage_type: str # Defined by provider (e.g. "main_image", "gallery")
|
|
|
|
|
|
class MediaUsageResponse(BaseModel):
|
|
"""Response showing where media is being used."""
|
|
|
|
media_id: int | None = None
|
|
usage: list[MediaUsageItem] = []
|
|
total_usage_count: int = 0
|
|
|
|
|
|
# ============================================================================
|
|
# MEDIA OPTIMIZATION SCHEMAS
|
|
# ============================================================================
|
|
|
|
|
|
class OptimizationResultResponse(BaseModel):
|
|
"""Response for media optimization operation."""
|
|
|
|
media_id: int | None = None
|
|
original_size: int | None = None
|
|
optimized_size: int | None = None
|
|
savings_percent: float | None = None
|
|
optimized_url: str | None = None
|
|
message: str | None = None
|