From 1b830f7bd2c44807e0f804ceba626f1d7abb3a90 Mon Sep 17 00:00:00 2001 From: Brian Wiborg Date: Mon, 29 Sep 2025 17:17:54 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20Reflect=20latest=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 29 ++++++++++++++++----- src/ohmyapi/core/runtime.py | 11 +++++--- src/ohmyapi/core/templates/app/routes.py.j2 | 9 ++++--- 3 files changed, 35 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 07a3dae..6996844 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ It is ***blazingly fast***, extremely ***fun to use*** and comes with ***batteri **Creating a Project** ``` -pip install ohmyapi +pipx install ohmyapi ohmyapi startproject myproject cd myproject ``` @@ -127,24 +127,29 @@ from ohmyapi.db.exceptions import DoesNotExist from .models import Tournament -# Expose your app's routes via `router = fastapi.APIRouter`. -# Use prefixes wisely to avoid cross-app namespace-collisions. +# OhMyAPI will automatically pick up all instances of `fastapi.APIRouter` and +# add their routes to the main project router. +# +# Note: +# Use prefixes wisely to avoid cross-app namespace-collisions! # Tags improve the UX of the OpenAPI docs at /docs. -router = APIRouter(prefix="/tournament", tags=['Tournament']) +# +tournament_router = APIRouter(prefix="/tournament", tags=['Tournament']) -@router.get("/") + +@tournament_router.get("/") async def list(): queryset = Tournament.all() return await Tournament.Schema.model.from_queryset(queryset) -@router.post("/", status_code=HTTPStatus.CREATED) +@tournament_router.post("/", status_code=HTTPStatus.CREATED) async def post(tournament: Tournament.Schema.readonly): queryset = Tournament.create(**payload.model_dump()) return await Tournament.Schema.model.from_queryset(queryset) -@router.get("/:id") +@tournament_router.get("/:id") async def get(id: str): try: queryset = Tournament.get(id=id) @@ -152,6 +157,16 @@ async def get(id: str): except DoesNotExist: raise HTTPException(status_code=404, detail="not found") + +@tournament_router.delete("/:id") +async def delete(id: str): + try: + tournament = await Tournament.get(id=id) + return await Tournament.Schema.model.from_queryset(tournament.delete()) + except DoesNotExist: + raise HTTPException(status_code=404, detail="not found") + + ... ``` diff --git a/src/ohmyapi/core/runtime.py b/src/ohmyapi/core/runtime.py index 380c56d..87127f8 100644 --- a/src/ohmyapi/core/runtime.py +++ b/src/ohmyapi/core/runtime.py @@ -211,7 +211,7 @@ class App: self.model_modules: List[str] = [] # The APIRouter - self.router: Optional[APIRouter] = None + self.router: APIRouter = APIRouter() # Import the app, so its __init__.py runs. importlib.import_module(self.name) @@ -226,9 +226,12 @@ class App: # Locate the APIRouter try: routes_mod = importlib.import_module(f"{self.name}.routes") - router = getattr(routes_mod, "router", None) - if isinstance(router, APIRouter): - self.router = router + for attr_name in dir(routes_mod): + if attr_name.startswith("__"): + continue + attr = getattr(routes_mod, attr_name) + if isinstance(attr, APIRouter): + self.router.include_router(attr) except ModuleNotFoundError: pass diff --git a/src/ohmyapi/core/templates/app/routes.py.j2 b/src/ohmyapi/core/templates/app/routes.py.j2 index dd1579a..3edc01e 100644 --- a/src/ohmyapi/core/templates/app/routes.py.j2 +++ b/src/ohmyapi/core/templates/app/routes.py.j2 @@ -4,13 +4,16 @@ from . import models from typing import List -# Expose your app's routes via `router = fastapi.APIRouter`. -# Use prefixes wisely to avoid cross-app namespace-collisions. +# OhMyAPI will automatically pick up all instances of `fastapi.APIRouter` and +# add their routes to the main project router. +# +# Note: +# Use prefixes wisely to avoid cross-app namespace-collisions! # Tags improve the UX of the OpenAPI docs at /docs. +# router = APIRouter(prefix="/{{ app_name }}", tags=['{{ app_name }}']) - @router.get("/") async def list(): """List all ..."""