Automated Action a9210ca8ed Create manga inventory API with FastAPI and SQLite
- Implemented CRUD operations for manga, authors, publishers, and genres
- Added search and filtering functionality
- Set up SQLAlchemy ORM with SQLite database
- Configured Alembic for database migrations
- Implemented logging with Loguru
- Added comprehensive API documentation
- Set up error handling and validation
- Added ruff for linting and formatting
2025-05-30 12:29:35 +00:00

117 lines
2.9 KiB
Python

from typing import Any
from fastapi import APIRouter, Depends, HTTPException, status
from sqlalchemy.orm import Session
from app import crud, schemas
from app.api import deps
router = APIRouter()
@router.get("/", response_model=list[schemas.Genre])
def read_genres(
db: Session = Depends(deps.get_db),
skip: int = 0,
limit: int = 100,
) -> Any:
"""
Retrieve genres.
"""
genres = crud.genre.get_multi(db, skip=skip, limit=limit)
return genres
@router.post("/", response_model=schemas.Genre)
def create_genre(
*,
db: Session = Depends(deps.get_db),
genre_in: schemas.GenreCreate,
) -> Any:
"""
Create new genre.
"""
genre = crud.genre.get_by_name(db, name=genre_in.name)
if genre:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="A genre with this name already exists.",
)
genre = crud.genre.create(db, obj_in=genre_in)
return genre
@router.get("/{genre_id}", response_model=schemas.Genre)
def read_genre(
*,
db: Session = Depends(deps.get_db),
genre_id: int,
) -> Any:
"""
Get genre by ID.
"""
genre = crud.genre.get(db, id=genre_id)
if not genre:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Genre not found",
)
return genre
@router.put("/{genre_id}", response_model=schemas.Genre)
def update_genre(
*,
db: Session = Depends(deps.get_db),
genre_id: int,
genre_in: schemas.GenreUpdate,
) -> Any:
"""
Update a genre.
"""
genre = crud.genre.get(db, id=genre_id)
if not genre:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Genre not found",
)
# Check if updating to an existing name
if genre_in.name and genre_in.name != genre.name:
existing_genre = crud.genre.get_by_name(db, name=genre_in.name)
if existing_genre:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="A genre with this name already exists.",
)
genre = crud.genre.update(db, db_obj=genre, obj_in=genre_in)
return genre
@router.delete("/{genre_id}", response_model=schemas.Genre)
def delete_genre(
*,
db: Session = Depends(deps.get_db),
genre_id: int,
) -> Any:
"""
Delete a genre.
"""
genre = crud.genre.get(db, id=genre_id)
if not genre:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Genre not found",
)
# Check if genre has manga associated with it
if genre.manga_list:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail="Cannot delete genre with associated manga. Remove manga first.",
)
genre = crud.genre.remove(db, id=genre_id)
return genre