FastAPI 子应用
3/8/2025
本文谈论 FastAPI 子应用。很可能你可能直接用上,但是有些开源项目用上了。这里简单的探索一下。
一、谁在用?
open-webui 使用就是 子应用 模式。开始之前希望读者对 FastAPI 框架有一些基本的认识。
二、与嵌套路由的区别
- 路由嵌套使用 APIRouter定义路由 组织,使用 app.add_router 添加路由。
- 子应用 FastAPI 添加应用,使用 app.mount 挂载子应用。
三、开始带有子应用的 FastAPI 应用
cd your dir
poetry init
poetry add fastapi[all] # 这里我们安装全功能版本
[tool.poetry.dependencies]
fastapi = {extras = ["all"], version = "^0.115.5"}
四、定义和挂载方式
- 在 fastapi 中 FastAPI 定义 app
- 在 fastapi 使用 app.mount 挂载子 app
- 使用 lifespan 定义生命周期
- 在生命周期中定义 state 状态
- 定义子应用
分别子应用的表现出来的特性。
五、主应用:main.py
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from middlewares.PM_Global import PM_Global
from user import app as user_app
@asynccontextmanager
async def lifespan(app: FastAPI):
app.state.config = {"app_name": "FastAPI Main"} # 在 app state 中定义 config 配置状态
print("Global life span")
yield
app = FastAPI(lifespan=lifespan) # 定义全局 app, 带有 lifespan
app.add_middleware(PM_Global, name="PM_Global") # 注册全局中间件
app.mount("/api/user", user_app) # 使用 app mount 挂载 user_app
@app.get("/")
async def root(request: Request):
print("main",request.app.state.__dict__) # 在接口中方位 app.state 的状态(状态成字典的形式)
return {"message": "Hello World"}
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", port=8000, reload=True)
使用 class 定义全局使用 PM_Global 中间件
from fastapi import Request
from starlette.middleware.base import BaseHTTPMiddleware
class PM_Global(BaseHTTPMiddleware):
def __init__(self, app, name: str):
super().__init__(app)
self.name = name
async def dispatch(self, request: Request, call_next):
print(f"Executing middleware Gloal: {self.name}") # 全局输出字符串
# 调用下一个中间件或最终的请求处理器
response = await call_next(request)
return response
中间件的内容:很简单输出带有 Global 字样的字符串.
六、子应用 user.py
from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from middlewares.PM_Sub1 import PM_Sub1
@asynccontextmanager
async def lifespan(app: FastAPI):
print("PM_Sub1 life span") # spanlife 生命周期
yield
app = FastAPI(lifespan=lifespan)
app.add_middleware(PM_Sub1, name="PM_Sub1") # 添加 user 的中间件
@app.get("/")
def read_root(request: Request):
print(request.app.state.__dict__) # 使用 request 访问 app 的状态。
return {"Hello": "World"}
七、启动 fastapi
poetry run main.py
我们看到 全局
的 中间件
已经执行了。下面看看子应用 user
看到全局的中间件先输出,子应用的中间件后输出。从两者的表现是中间件在应用中是独立的。
八、访问 docs
访问一下 docs, 子应用有自己的 docs 地址:
http://127.0.0.1:8000/docs
http://127.0.0.1:8000/api/user/docs
九、查看 state 状态
- 访问接口
/
发现 主应用
的状态能够正常访问。
- 访问
/api/user
副应用由于没有添加数据,所有访问是一个空字典。由此也可以从实践中得出,子应用与主应用 state 是独立的。我们不能直接在子应用中获取主应用的路径。
十、使用场景
- 多模块开发:用户模块、文章模块
- 版本控制: v1/v2 不同的版本
- 需要演进(微服务)的项目
如果的你项目足够小,使用子应用可能会过渡设计。子应用适合有一定的的规模的项目。同时便于团队合作。
十一、小结
本文主要探索 FastAPI 主要子应用的基本使用和适用场景。子应用使用 FastAPI 构造,需要 mount 进行挂载子应用。子应用在中间件
、状态管理
、文档
、生命周期
等独立。子应用在多模块开发和版本管理时有较大的用处。