FastAPI路由
# FastAPI路由
# 路由介绍
FastAPI 本身不强制规定项目结构,但随着项目规模增长,合理的路由组织和目录划分对可维护性、可读性和团队协作至关重要。
使用 APIRouter 有以下作用:
- 模块化:每个功能模块(如用户、商品)有自己的路由文件。
- 可复用:同一个Router可被多个应用挂载。
- 可嵌套:支持资源嵌套路由。
- 统一前缀 & 标签:自动为一组路由添加路径前缀和Swagger分组标签。
- 依赖注入作用域:可在Router级别设置通用依赖。
# 路由使用
APIRouter 是用于组织和模块化路由的核心工具。它能够将API端点拆分成多个独立的、可复用的"子应用",然后在主应用中统一挂载,从而避免所有路由都堆积在单个文件中。
include_router 则是用于将 APIRouter 实例挂载到主应用上的核心方法。
api/users.py 子路由模块
# routes/users.py
from fastapi import APIRouter
# 定义子路由
router = APIRouter()
@router.get("/users/")
def read_users():
return [{"name": "Alice"}, {"name": "Bob"}]
@router.get("/users/{user_id}")
def read_user(user_id: int):
return {"user_id": user_id, "name": "Alice"}
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
main.py 主应用中挂在子路由模块
from fastapi import FastAPI
from api import users, auth
app = FastAPI()
# 挂载用户路由,可挂在多个
app.include_router(users.router)
app.include_router(auth.router)
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
# 路由参数
APIRouter 中的参数都可以在 include_router() 中使用,推荐在 include_router() 中使用,以便于统一管理。
# 统一路径前缀
APIRouter(prefix="路径前缀") 用于设置该路由的统一的路径前缀。
router = APIRouter(prefix="/api/v1")
# 或
app.include_router(user_router, prefix="/api/v1")
1
2
3
2
3
# 路由分组标签
APIRouter(tag=["标签1", "标签2", ...]) 用于设置该路由的标签。添加标签后,Swagger文档中会对接口进行分组,提升文档可读性。
router = APIRouter(tags=["Users"])
# 或
app.include_router(user_router, tags=["Users"])
1
2
3
2
3
# 统一错误响应
APIRouter(responses={状态码: {"description": "描述"}}) 用于设置统一的错误响应。
router = APIRouter(
responses={404: {"description": "Not found"}}
)
1
2
3
2
3
# 路由依赖注入
APIRouter(dependencies=[Depends(依赖项函数), ...]) 用于设置路由级的依赖注入。
from fastapi import Depends, HTTPException
def verify_token(token: str):
if token != "secret":
raise HTTPException(status_code=403, detail="Invalid token")
return token
# 该路由下的路径都需要验证
router = APIRouter(
dependencies=[Depends(verify_token)]
)
@router.get("/profile")
def get_profile():
return {"data": "protected"}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 嵌套路由
路由之间可以进行嵌套,适用于资源嵌套场景。
# api/v1/users.py
from fastapi import APIRouter
# 父路由处理/users/
router = APIRouter(prefix="/users")
# 子路由处理/{user_id}/posts
posts_router = APIRouter()
@posts_router.get("/")
def get_user_posts(user_id: int):
return [{"title": "Post 1", "user_id": user_id}]
# 将posts_router嵌套到users路由下
# 最终子路由路径为/users/123/posts,user_id会被父路由捕获并传给子路由
router.include_router(posts_router, prefix="/{user_id}/posts")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16