skip: int = Query(0, ge=0),
limit: int = Query(10, le=100),
category: Optional[str] = None,
tags: List[str] = Query([])
):
return {'skip': skip, 'limit': limit, 'category': category, 'tags': tags}
# Request body + path param + query param together
@[Link]('/items/{item_id}')
async def update_item(
item_id: int,
item: ItemUpdate,
notify: bool = False
):
return {'item_id': item_id, 'data': item, 'notify': notify}
🎯 Q: How does FastAPI differentiate between path, query, and body parameters?
✅ Answer:
FastAPI uses Python type hints and function signatures to automatically determine parameter types.
If a parameter name matches a path variable in the route decorator, it's a path parameter. If it's a
simple type (str, int, bool) not in the path, it's treated as a query parameter. If it's a Pydantic
BaseModel, it's treated as a request body. You can also be explicit using Path(), Query(), Body()
from fastapi.
2.2 APIRouter — Organizing Routes
# routers/[Link]
from fastapi import APIRouter
router = APIRouter(
prefix="/users",
tags=["Users"],
responses={404: {"description": "Not found"}}
)
@[Link]('/')
async def list_users():
return []
@[Link]('/{user_id}')
async def get_user(user_id: int):
return {'id': user_id}
# [Link]
from fastapi import FastAPI
from routers import users, products, orders
app = FastAPI()
app.include_router([Link])
app.include_router([Link])
app.include_router([Link])
🎯 Q: How do you organize a large FastAPI application?
✅ Answer:
Use APIRouter to split routes into separate modules by feature or domain (users, products, orders).
Each router has its own prefix and tags. The main app includes all routers using
app.include_router(). For larger apps, follow a layered architecture: routers (HTTP layer) → services