from fastapi import APIRouter, Depends, Query from sqlalchemy import func, select from sqlalchemy.ext.asyncio import AsyncSession from core.authx import auth from core.db import get_db from models.photo_model import Category, Photo from schemas.photo_schemas import CategoriesOut, PhotosOut, PhotosPaginatedOut router = APIRouter() @router.get("/photos", response_model=PhotosPaginatedOut, dependencies=[Depends(auth.access_token_required)]) async def get_photos( page: int = Query(1, ge=1), per_page: int = Query(24, ge=1), session: AsyncSession = Depends(get_db), # noqa: B008 category: int | None = None, ): offset = (page - 1) * per_page query = select(Photo) if category is not None: query = query.where(Photo.category_id == category) query = query.order_by(Photo.id).offset(offset).limit(per_page) result = await session.execute(query) photos = result.scalars().all() return { "photos": photos, "page_inc": f"/photos?page={page + 1}&per_page={per_page}&category={category}", "page_dec": f"/photos?page={max(1, page - 1)}&per_page={per_page}&category={category}", } @router.get("/categories", response_model=CategoriesOut, dependencies=[Depends(auth.access_token_required)]) async def categories(session: AsyncSession = Depends(get_db)): # noqa: B008 stmt = ( select(Category.id, Category.title, func.count(Photo.id).label("photos_count")) .select_from(Category) .outerjoin(Category.photos) .group_by(Category.id, Category.title) .order_by(Category.title) ) rows = (await session.execute(stmt)).all() return { "categories": [ {"id": r.id, "title": r.title, "photos_count": r.photos_count} for r in rows ] } @router.get("/category", response_model=PhotosOut) async def category( page: int = Query(1, ge=1), per_page: int = Query(24, ge=1), session: AsyncSession = Depends(get_db), # noqa: B008 id: int = Query(...), ): offset = (page - 1) * per_page query = ( select(Photo) .where(Photo.category_id == id) .order_by(Photo.id) .offset(offset) .limit(per_page) ) result = await session.execute(query) photos = result.scalars().all() return {"photos": photos}