Replies: 3 comments
-
Router Import StrategyAddressing #574 (comment) Option A: Module import +
|
| Pros | Cons |
|---|---|
| Clear which module each router comes from | Two lines per route (import + include) |
| Easy to access other module-level attributes if needed | Import line grows long with many modules |
| Most common pattern in FastAPI projects | - |
Option B: Direct router import with alias
from app.api.routes.forms import router as forms_router
from app.api.routes.templates import router as templates_router
from app.api.routes.jobs import router as jobs_router
api_router = APIRouter()
api_router.include_router(templates_router)
api_router.include_router(forms_router)
api_router.include_router(jobs_router)| Pros | Cons |
|---|---|
| Explicit - each import names exactly what it brings in | Verbose alias needed for every route to avoid name collisions |
| No intermediate module reference | More lines as route count grows |
| - | as aliases can drift from actual module names |
Option C: Unique router names per module
# routes/forms.py
forms_router = APIRouter(prefix="/forms", tags=["forms"])
# routes/templates.py
templates_router = APIRouter(prefix="/templates", tags=["templates"])
# router.py
from app.api.routes.forms import forms_router
from app.api.routes.templates import templates_router
api_router = APIRouter()
api_router.include_router(templates_router)
api_router.include_router(forms_router)This is the pattern used by v1_router in the current codebase each module exports a uniquely named router variable.
| Pros | Cons |
|---|---|
| No alias needed, no name collision | Requires renaming router to <module>_router in every route file |
Imports are explicit without module.router indirection |
Breaks the standard FastAPI convention where route files export router |
| - | Touches every route file in the codebase large diff for no functional gain |
Recommendation
Option A - it's the standard FastAPI pattern, scales cleanly, and avoids alias noise. One import line pulls in all modules, and module.router makes it obvious where each router lives.
from app.api.routes import forms, jobs, system, templates
api_router = APIRouter()
api_router.include_router(templates.router)
api_router.include_router(forms.router)
api_router.include_router(jobs.router)
api_router.include_router(system.router)Beta Was this translation helpful? Give feedback.
-
|
@marcvergees @abhishek-8081 |
Beta Was this translation helpful? Give feedback.
-
|
Clearly "Option A": faster, cleaner and modularized. Can you @abhishek-8081 PR the changes so that what you created in a new folder Thanks. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
A review comment on PR #574 pointed out the import strategy for the jobs router it was being added directly to
api_routerinstead of going throughv1_router. This got me looking at the last few merged PRs and the current codebase structure, where I noticed we now have two parallel structures for API routes. I also did some research across open-source FastAPI projects to see how they handle this.The
v1/folder approach (introduced in PR #573) does achieve the/api/v1/...URL pattern that our OpenAPI contract requires. However, when I originally created the contracts and proposed the codebase structure in Discussion #501, I had a different approach in mind that I didn't get to implement at the time I intentionally did not include av1/versioning folder in the proposed structure.Current state
Right now we have two parallel structures:
This is inconsistent some endpoints are versioned, some aren't. If we commit to the
v1/folder approach, we'd need to migrate all existing routes, schemas, and potentially models into the versioned folder.My proposal: config-based prefix (no versioning folder)
Add a single constant in
config.py:Mount all routes under this prefix in
router.py:Resulting structure stays flat:
All endpoints still resolve to
/api/v1/templates,/api/v1/forms, etc. matching our OpenAPI contract exactly. If we ever need to bump, we change one string.Why not a
v1/folder?v1/now means moving all existing routes, schemas into it. Every open PR would conflict.api/routes/and others inapi/v1/routes/. One flat structure is simpler.What stays the same
/api/v1/templates,/api/v1/forms, etc.routes → services → repositories → databaseBeta Was this translation helpful? Give feedback.
All reactions