Automated Action 0186fc8e70 Create movie database backend with FastAPI and SQLite
This commit implements a simple movie database backend inspired by IMDb. It includes:
- API endpoints for movies, actors, directors and genres
- SQLAlchemy models with relationships
- Alembic migrations
- Pydantic schemas for request/response validation
- Search and filtering functionality
- Health check endpoint
- Complete documentation
2025-05-19 20:28:07 +00:00

120 lines
3.1 KiB
Python

from typing import Any, List, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, Path
from sqlalchemy.orm import Session
from app.api import crud
from app.api.schemas.movie import (
Movie, MovieCreate, MovieUpdate, MovieDetails, MovieList
)
from app.db.session import get_db
router = APIRouter(prefix="/movies")
@router.get("", response_model=MovieList)
def read_movies(
db: Session = Depends(get_db),
skip: int = Query(0, ge=0),
limit: int = Query(100, ge=1, le=100),
title: Optional[str] = None,
director_id: Optional[int] = None,
genre_id: Optional[int] = None,
actor_id: Optional[int] = None,
min_rating: Optional[float] = Query(None, ge=0, le=10),
year: Optional[int] = None,
) -> Any:
"""
Retrieve all movies with optional filtering.
"""
# Build filter dict from query parameters
filters = {}
if title:
filters["title"] = title
if director_id:
filters["director_id"] = director_id
if genre_id:
filters["genre_id"] = genre_id
if actor_id:
filters["actor_id"] = actor_id
if min_rating is not None:
filters["min_rating"] = min_rating
if year:
filters["year"] = year
movies, total = crud.movie.get_multi(db, skip=skip, limit=limit, filters=filters)
return {"data": movies, "total": total}
@router.post("", response_model=Movie, status_code=201)
def create_movie(
*,
db: Session = Depends(get_db),
movie_in: MovieCreate,
) -> Any:
"""
Create a new movie.
"""
movie = crud.movie.create(db, movie_in=movie_in)
return movie
@router.get("/{movie_id}", response_model=MovieDetails)
def read_movie(
*,
db: Session = Depends(get_db),
movie_id: int = Path(..., ge=1),
) -> Any:
"""
Get a specific movie by ID.
"""
movie = crud.movie.get(db, movie_id=movie_id)
if not movie:
raise HTTPException(status_code=404, detail="Movie not found")
return movie
@router.put("/{movie_id}", response_model=Movie)
def update_movie(
*,
db: Session = Depends(get_db),
movie_id: int = Path(..., ge=1),
movie_in: MovieUpdate,
) -> Any:
"""
Update a movie.
"""
movie = crud.movie.get(db, movie_id=movie_id)
if not movie:
raise HTTPException(status_code=404, detail="Movie not found")
movie = crud.movie.update(db, db_movie=movie, movie_in=movie_in)
return movie
@router.delete("/{movie_id}", status_code=204, response_model=None)
def delete_movie(
*,
db: Session = Depends(get_db),
movie_id: int = Path(..., ge=1),
) -> Any:
"""
Delete a movie.
"""
success = crud.movie.delete(db, movie_id=movie_id)
if not success:
raise HTTPException(status_code=404, detail="Movie not found")
return None
@router.get("/search/{query}", response_model=List[Movie])
def search_movies(
*,
db: Session = Depends(get_db),
query: str = Path(..., min_length=2),
limit: int = Query(10, ge=1, le=100),
) -> Any:
"""
Search for movies by title or overview.
"""
movies = crud.movie.search(db, query=query, limit=limit)
return movies