Spaces:
Sleeping
Sleeping
| """ | |
| Photo Model β ORM + Pydantic Schemas | |
| ORM: Photo (SQLAlchemy table: photos) | |
| Schemas: PhotoCreate, PhotoResponse | |
| """ | |
| import uuid | |
| from datetime import datetime | |
| from typing import Optional | |
| from sqlalchemy import String, Text, BigInteger, DateTime, ForeignKey, func | |
| from sqlalchemy.dialects.postgresql import UUID | |
| from sqlalchemy.orm import Mapped, mapped_column, relationship | |
| from pydantic import BaseModel, Field, ConfigDict | |
| from models.base import Base | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # ORM Model | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class Photo(Base): | |
| """SQLAlchemy ORM model for the 'photos' table.""" | |
| __tablename__ = "photos" | |
| id: Mapped[uuid.UUID] = mapped_column( | |
| UUID(as_uuid=True), primary_key=True, default=uuid.uuid4 | |
| ) | |
| visit_id: Mapped[uuid.UUID] = mapped_column( | |
| UUID(as_uuid=True), | |
| ForeignKey("visits.id", ondelete="CASCADE"), | |
| nullable=False, | |
| ) | |
| checklist_id: Mapped[Optional[uuid.UUID]] = mapped_column( | |
| UUID(as_uuid=True), | |
| ForeignKey("checklists.id", ondelete="SET NULL"), | |
| nullable=True, | |
| ) | |
| assessment_id: Mapped[Optional[uuid.UUID]] = mapped_column( | |
| UUID(as_uuid=True), | |
| ForeignKey("assessments.id", ondelete="SET NULL"), | |
| nullable=True, | |
| comment="Linked assessment item (for per-item photo gallery)" | |
| ) | |
| file_path: Mapped[str] = mapped_column(String(500), nullable=False) | |
| file_name: Mapped[str] = mapped_column(String(255), nullable=False) | |
| file_size: Mapped[Optional[int]] = mapped_column(BigInteger, nullable=True) | |
| mime_type: Mapped[Optional[str]] = mapped_column(String(100), nullable=True) | |
| caption: Mapped[Optional[str]] = mapped_column(Text, nullable=True) | |
| uploaded_at: Mapped[datetime] = mapped_column( | |
| DateTime, server_default=func.now() | |
| ) | |
| created_at: Mapped[datetime] = mapped_column( | |
| DateTime, server_default=func.now() | |
| ) | |
| # Relationships | |
| visit = relationship("Visit", back_populates="photos") | |
| checklist = relationship("Checklist", back_populates="photos", foreign_keys=[checklist_id]) | |
| assessment = relationship("Assessment", back_populates="photos", foreign_keys=[assessment_id]) | |
| def __repr__(self) -> str: | |
| return f"<Photo(id={self.id}, file='{self.file_name}')>" | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| # Pydantic Schemas | |
| # ββββββββββββββββββββββββββββββββββββββββββββββββββ | |
| class PhotoCreate(BaseModel): | |
| """Schema for photo upload metadata.""" | |
| checklist_id: Optional[uuid.UUID] = Field( | |
| None, description="Optional linked checklist item" | |
| ) | |
| assessment_id: Optional[uuid.UUID] = Field( | |
| None, description="Optional linked assessment item (per-item photo)" | |
| ) | |
| caption: Optional[str] = Field(None, description="Photo caption") | |
| class PhotoResponse(BaseModel): | |
| """Schema for a single photo in API responses.""" | |
| model_config = ConfigDict(from_attributes=True) | |
| id: uuid.UUID | |
| visit_id: uuid.UUID | |
| checklist_id: Optional[uuid.UUID] | |
| assessment_id: Optional[uuid.UUID] | |
| file_path: str | |
| file_name: str | |
| file_size: Optional[int] | |
| mime_type: Optional[str] | |
| caption: Optional[str] | |
| uploaded_at: datetime | |
| created_at: datetime | |