When I sperate apis into multiple module, I find it hard to structure the code, currently I approach like this:
# app.py
from fastapi import FastAPI
app = FastAPI()
# api1.py
from app import app
@app.get('/test1')
...
# api2.py
from app import app
@app.get('/test2')
...
# main.py
from app import app
import api1
import api2
$ uvicorn main:app --lifespan on
...
Any suggestions?
From the FastAPI project-generator codebase:
# app/api/api_v1/endpoints/items.py
...
from fastapi import APIRouter, Depends, HTTPException
...
router = APIRouter()
@router.get("/", response_model=List[Item])
...
```python
from fastapi import APIRouter
from app.api.api_v1.endpoints import items, login, users, utils
api_router = APIRouter()
api_router.include_router(login.router, tags=["login"])
api_router.include_router(users.router, prefix="/users", tags=["users"])
api_router.include_router(utils.router, prefix="/utils", tags=["utils"])
api_router.include_router(items.router, prefix="/items", tags=["items"])
```python
# app/main.py
from fastapi import FastAPI
...
from app.api.api_v1.api import api_router
...
app = FastAPI(title=config.PROJECT_NAME, openapi_url="/api/v1/openapi.json")
...
app.include_router(api_router, prefix=config.API_V1_STR)
...
Great, thanks!
Thanks @dmontagu! : 馃嵃
@yihuang the docs about that are here: https://fastapi.tiangolo.com/tutorial/bigger-applications/
Hi, guys, I think this is great, thanks. But when using this strategy, It's easy to get 302, why?
For example:
test_client.get("/api/v1/items") # 302
test_client.get("/api/v1/items/") # OK
@markqiu it鈥檚 because you are creating an endpoint with path "/" mounted at ".../items". So the full endpoint path is ".../items/". The 302 is because the system realizes that /items isn鈥檛 a valid endpoint, and you probably meant ".../items/", so it redirects.
If you don鈥檛 want your paths to end in a / (eg if you are using a client library that likes to remove trailing slashes... been there...), make sure you never have paths ending in / in the endpoint decorators (this includes just a single slash).
@dmontagu But If a path includes just a single slash, you can't define the endpoint decorators like this:
@router.get("", response_model=List[Item])
Right, you'd have to give it a name (e.g. @router.get("/items", response_model=List[Item])).
You can mount multiple routers with the same prefix if, for example, you want to have multiple distinct resources with the same prefix and different non-slash-ending endpoints:
from fastapi import FastAPI, APIRouter
app = FastAPI()
router1 = APIRouter()
router2 = APIRouter()
@router1.get("/items")
async def read_items():
return []
@router2.get("/things")
async def read_things():
return []
app.include_router(router1, prefix="")
app.include_router(router2, prefix="")
if __name__ == '__main__':
import uvicorn
uvicorn.run(app, host='0.0.0.0', port=8000)
ok, thanks.
Most helpful comment
From the FastAPI project-generator codebase:
```python
app/api/api_v1/api.py
from fastapi import APIRouter
from app.api.api_v1.endpoints import items, login, users, utils
api_router = APIRouter()
api_router.include_router(login.router, tags=["login"])
api_router.include_router(users.router, prefix="/users", tags=["users"])
api_router.include_router(utils.router, prefix="/utils", tags=["utils"])
api_router.include_router(items.router, prefix="/items", tags=["items"])