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 typing import List, Optional, Union
from uuid import UUID
from typing import List, Optional
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
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(
book_id: Optional[UUID] = Query(None, description="ID of the book to retrieve"),
skip: int = Query(0, description="Number of records to skip"),
author: Optional[str] = Query(None, description="Filter books by author name"),
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"),
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.
Otherwise, returns a list of books with pagination.
- If author is provided, returns all books by that author
- 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:
book = get_book_by_id(db, book_id)
if not book:
raise HTTPException(status_code=404, detail="Book not found")
return book
if author and not title:
books = get_books_by_author(db, author=author, skip=skip, limit=limit)
elif title and not author:
books = get_books_by_title(db, title=title, skip=skip, limit=limit)
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

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()
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:
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.
limit (int, optional): Maximum number of records to return. Defaults to 100.
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()