phase 5
This commit is contained in:
112
backend/app/images/schemas.py
Normal file
112
backend/app/images/schemas.py
Normal file
@@ -0,0 +1,112 @@
|
||||
"""Image schemas for request/response validation."""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import Any
|
||||
from uuid import UUID
|
||||
|
||||
from pydantic import BaseModel, Field, field_validator
|
||||
|
||||
|
||||
class ImageMetadata(BaseModel):
|
||||
"""Image metadata structure."""
|
||||
|
||||
format: str = Field(..., description="Image format (jpeg, png, etc)")
|
||||
checksum: str = Field(..., description="SHA256 checksum of file")
|
||||
exif: dict[str, Any] | None = Field(None, description="EXIF data if available")
|
||||
thumbnails: dict[str, str] = Field(default_factory=dict, description="Thumbnail URLs by quality level")
|
||||
|
||||
|
||||
class ImageUploadResponse(BaseModel):
|
||||
"""Response after successful image upload."""
|
||||
|
||||
id: UUID
|
||||
filename: str
|
||||
storage_path: str
|
||||
file_size: int
|
||||
mime_type: str
|
||||
width: int
|
||||
height: int
|
||||
metadata: dict[str, Any]
|
||||
created_at: datetime
|
||||
|
||||
class Config:
|
||||
"""Pydantic config."""
|
||||
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class ImageResponse(BaseModel):
|
||||
"""Full image response with all fields."""
|
||||
|
||||
id: UUID
|
||||
user_id: UUID
|
||||
filename: str
|
||||
storage_path: str
|
||||
file_size: int
|
||||
mime_type: str
|
||||
width: int
|
||||
height: int
|
||||
metadata: dict[str, Any]
|
||||
created_at: datetime
|
||||
reference_count: int
|
||||
|
||||
class Config:
|
||||
"""Pydantic config."""
|
||||
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class BoardImageCreate(BaseModel):
|
||||
"""Schema for adding image to board."""
|
||||
|
||||
image_id: UUID = Field(..., description="ID of uploaded image")
|
||||
position: dict[str, float] = Field(default_factory=lambda: {"x": 0, "y": 0}, description="Canvas position")
|
||||
transformations: dict[str, Any] = Field(
|
||||
default_factory=lambda: {
|
||||
"scale": 1.0,
|
||||
"rotation": 0,
|
||||
"opacity": 1.0,
|
||||
"flipped_h": False,
|
||||
"flipped_v": False,
|
||||
"greyscale": False,
|
||||
},
|
||||
description="Image transformations",
|
||||
)
|
||||
z_order: int = Field(default=0, description="Layer order")
|
||||
|
||||
@field_validator("position")
|
||||
@classmethod
|
||||
def validate_position(cls, v: dict[str, float]) -> dict[str, float]:
|
||||
"""Validate position has x and y."""
|
||||
if "x" not in v or "y" not in v:
|
||||
raise ValueError("Position must contain 'x' and 'y' coordinates")
|
||||
return v
|
||||
|
||||
|
||||
class BoardImageResponse(BaseModel):
|
||||
"""Response for board image with all metadata."""
|
||||
|
||||
id: UUID
|
||||
board_id: UUID
|
||||
image_id: UUID
|
||||
position: dict[str, float]
|
||||
transformations: dict[str, Any]
|
||||
z_order: int
|
||||
group_id: UUID | None
|
||||
created_at: datetime
|
||||
updated_at: datetime
|
||||
image: ImageResponse
|
||||
|
||||
class Config:
|
||||
"""Pydantic config."""
|
||||
|
||||
from_attributes = True
|
||||
|
||||
|
||||
class ImageListResponse(BaseModel):
|
||||
"""Paginated list of images."""
|
||||
|
||||
images: list[ImageResponse]
|
||||
total: int
|
||||
page: int
|
||||
page_size: int
|
||||
Reference in New Issue
Block a user