diff --git a/Dockerfile b/Dockerfile index 1b1cb15..54155c1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ # syntax=docker/dockerfile:1 -ARG PYTHON_VERSION=3.9.6 +ARG PYTHON_VERSION=3.10.14 FROM python:${PYTHON_VERSION}-slim AS base # Prevents Python from writing pyc files. diff --git a/app/routers/games.py b/app/routers/games.py index 62ac6ea..240efce 100644 --- a/app/routers/games.py +++ b/app/routers/games.py @@ -64,8 +64,34 @@ def create_game(game: schemas.GameCreate, db: Session = Depends(get_db)): # TODO - when this is updated to support sorting, also update `app/routers/seed.py:all_in_one` to take advantage of it # TODO - and `latest_game` @api_router.get("/list", response_model=list[schemas.Game]) -def list_games(skip: int = 0, limit: int = 100, db=Depends(get_db)): - return crud.get_games(db, skip=skip, limit=limit) +def list_games( + skip: int = 0, limit: int = 100, sort_by="id", sort_order="asc", db=Depends(get_db) +): + match sort_by: + case "id": + return crud.get_games( + db, skip=skip, limit=limit, sort_by=sort_by, sort_order=sort_order + ) + case "winning_deck": + sort_by_column = ( + models.Deck.name.desc() if sort_order == "desc" else models.Deck.name + ) + return ( + db.query(models.Game) + .join(models.Deck, models.Game.winning_deck_id == models.Deck.id) + .order_by(sort_by_column) + .offset(skip) + .limit(limit) + .all() + ) + case _: + raise HTTPException( + # TODO - would be really cool if there was a way to reference the called-URL from this message! + # For more genericized code. Maybe can do this by setting `request: Request` in the function signature + # and referencing it? + status_code=400, + detail="Unsupported sort_by for /api/", + ) # This is helpful for at least the `all_in_one` data-seed path, but it could conceivably also be useful for a @@ -135,7 +161,9 @@ def game_create_html(request: Request, db=Depends(get_db)): # TODO - pagination @html_router.get("/list") def games_html(request: Request, db=Depends(get_db)): - games = list_games(db=db) + query_parameters = request.query_params + # `**query_parameters` expands the object as named-params to the function - setting `limit` and `offset` appropriately + games = list_games(db=db, **query_parameters) # TODO - a more "data-intensive application" implementation would fetch only the decks involved in the games for # this page decks = crud.get_decks(db=db, limit=-1) diff --git a/app/sql/crud.py b/app/sql/crud.py index d576626..8212e15 100644 --- a/app/sql/crud.py +++ b/app/sql/crud.py @@ -53,8 +53,23 @@ def get_game_by_id(db: Session, game_id: int): return db.query(models.Game).filter(models.Game.id == game_id).first() -def get_games(db: Session, skip: int = 0, limit: int = 100): - return db.query(models.Game).offset(skip).limit(limit).all() +def get_games( + db: Session, skip: int = 0, limit: int = 100, sort_by="id", sort_order="asc" +): + if hasattr(models.Game, sort_by): + if sort_order == "desc": + sort_by_column = getattr(models.Game, sort_by).desc() + else: + sort_by_column = getattr(models.Game, sort_by) + else: + # This will intentionally throw and error, but I don't know how else to interecept this. + # Basically this means that `sort_by` was not set to a legal attribute of `models.Game`. + # (We could just default to `sort_by_column = models.Game.id` here to keep going, but in practice I think we'd + # rather know something went wrong.) + sort_by_column = getattr(models.Game, sort_by) + return ( + db.query(models.Game).order_by(sort_by_column).offset(skip).limit(limit).all() + ) def create_game(db: Session, game: schemas.GameCreate):