feat: add filtering books by author or title

This commit is contained in:
Backend IM Bot 2025-04-29 19:56:12 +00:00
parent d2e18dd528
commit ed72288eb1
2 changed files with 33 additions and 21 deletions

View File

@ -1,32 +1,34 @@
from fastapi import APIRouter, Depends, HTTPException, Query from fastapi import APIRouter, Depends, Query, status
from sqlalchemy.orm import Session from sqlalchemy.orm import Session
from typing import List, Optional, Union from typing import List, Optional
from uuid import UUID
from core.database import get_db from core.database import get_db
from helpers.book_helpers import get_all_books, get_book_by_id from helpers.book_helpers import get_all_books, get_books_by_author, get_books_by_title
from schemas.book import BookSchema from schemas.book import BookSchema
router = APIRouter() router = APIRouter()
@router.get("/books", response_model=Union[List[BookSchema], BookSchema]) @router.get("/books", response_model=List[BookSchema], status_code=status.HTTP_200_OK)
async def get_books( async def get_books(
book_id: Optional[UUID] = Query(None, description="ID of the book to retrieve"), author: Optional[str] = Query(None, description="Filter books by author name"),
skip: int = Query(0, description="Number of records to skip"), title: Optional[str] = Query(None, description="Filter books by title or partial title match"),
skip: int = Query(0, description="Number of records to skip for pagination"),
limit: int = Query(100, description="Maximum number of records to return"), limit: int = Query(100, description="Maximum number of records to return"),
db: Session = Depends(get_db) db: Session = Depends(get_db)
): ):
""" """
Get books with optional filtering by ID. Get all books with optional filtering by author or title.
If book_id is provided, returns a single book. - If author is provided, returns all books by that author
Otherwise, returns a list of books with pagination. - If title is provided, returns all books with matching title (partial match)
- If both are provided, returns books matching both criteria
- If neither is provided, returns all books
""" """
if book_id: if author and not title:
book = get_book_by_id(db, book_id) books = get_books_by_author(db, author=author, skip=skip, limit=limit)
if not book: elif title and not author:
raise HTTPException(status_code=404, detail="Book not found") books = get_books_by_title(db, title=title, skip=skip, limit=limit)
return book else:
books = get_all_books(db, author=author, title=title, skip=skip, limit=limit)
books = get_all_books(db, skip=skip, limit=limit)
return books return books

View File

@ -108,16 +108,26 @@ def get_books_by_title(db: Session, title: str, skip: int = 0, limit: int = 100)
""" """
return db.query(Book).filter(Book.title.ilike(f"%{title}%")).offset(skip).limit(limit).all() return db.query(Book).filter(Book.title.ilike(f"%{title}%")).offset(skip).limit(limit).all()
def get_all_books(db: Session, skip: int = 0, limit: int = 100) -> List[Book]: def get_all_books(db: Session, author: Optional[str] = None, title: Optional[str] = None, skip: int = 0, limit: int = 100) -> List[Book]:
""" """
Retrieves all books with pagination. Retrieves all books with optional filtering by author or title and pagination.
Args: Args:
db (Session): The database session. db (Session): The database session.
author (Optional[str], optional): The author name to filter by. Defaults to None.
title (Optional[str], optional): The title or partial title to search for. Defaults to None.
skip (int, optional): Number of records to skip for pagination. Defaults to 0. skip (int, optional): Number of records to skip for pagination. Defaults to 0.
limit (int, optional): Maximum number of records to return. Defaults to 100. limit (int, optional): Maximum number of records to return. Defaults to 100.
Returns: Returns:
List[Book]: A list of book objects. List[Book]: A list of book objects matching the filters.
""" """
return db.query(Book).offset(skip).limit(limit).all() query = db.query(Book)
if author:
query = query.filter(Book.author == author)
if title:
query = query.filter(Book.title.ilike(f"%{title}%"))
return query.offset(skip).limit(limit).all()