FastAPI使用APIRouter时如何正确处理MongoDB连接?
解决FastAPI拆分应用后路由无法访问数据库连接的问题
你的错误原因很明确:你把MongoDB的连接实例挂载到了app对象上,但你在路由文件里试图从APIRouter对象(也就是router)上去访问Admin属性,这两个对象完全独立,自然会报AttributeError。下面是几种靠谱的解决方式,按推荐程度排序:
方法一:使用FastAPI依赖注入(官方推荐)
这种方式符合FastAPI的设计理念,解耦性最好,也方便后续测试。
- 主文件中定义获取数据库连接的依赖函数:
# Main.py from fastapi import FastAPI, Depends from motor.motor_asyncio import AsyncIOMotorClient from admin_routes import router as admin_router app = FastAPI() # 启动时创建MongoDB连接 @app.on_event("startup") async def startup_db_client(): app.mongodb_client = AsyncIOMotorClient("mongodb://localhost:27017") app.admin_db = app.mongodb_client["admin_db"] @app.on_event("shutdown") async def shutdown_db_client(): app.mongodb_client.close() # 定义依赖函数,提供数据库连接 def get_admin_db(): return app.admin_db # 挂载路由 app.include_router(admin_router)
- 在路由文件中通过
Depends调用该依赖:
# admin_routes.py from fastapi import APIRouter, Depends from Main import get_admin_db router = APIRouter(prefix="/admin") @router.get("/users") async def get_admin_users(admin_db = Depends(get_admin_db)): # 直接使用admin_db执行CRUD操作 users = await admin_db["users"].find().to_list(100) return users
方法二:通过Request对象访问app.state
如果不想用依赖注入,也可以通过Request对象拿到app实例,进而访问挂载的数据库连接:
- 主文件里把数据库连接放到
app.state(官方推荐的挂载自定义属性的位置):
# Main.py @app.on_event("startup") async def startup_db_client(): client = AsyncIOMotorClient("mongodb://localhost:27017") app.state.admin_db = client["admin_db"]
- 路由文件里注入
Request对象,然后访问app.state:
# admin_routes.py from fastapi import APIRouter, Request router = APIRouter(prefix="/admin") @router.get("/users") async def get_admin_users(request: Request): admin_db = request.app.state.admin_db users = await admin_db["users"].find().to_list(100) return users
方法三:全局数据库对象(适合小型项目)
这种方式最简单,但耦合性高,不适合大型项目的长期维护:
- 新建
db.py文件,定义全局变量:
# db.py admin_db = None
- 主文件启动时给全局变量赋值:
# Main.py from db import admin_db @app.on_event("startup") async def startup_db_client(): client = AsyncIOMotorClient("mongodb://localhost:27017") global admin_db admin_db = client["admin_db"]
- 路由文件直接导入全局变量使用:
# admin_routes.py from fastapi import APIRouter from db import admin_db router = APIRouter(prefix="/admin") @router.get("/users") async def get_admin_users(): users = await admin_db["users"].find().to_list(100) return users
总结一下,优先用方法一的依赖注入,它能让你的代码更清晰、更易于测试和扩展;如果是小型项目图省事,可以用方法三;方法二则是介于两者之间的折中方案。
内容的提问来源于stack exchange,提问作者M_Arad
相关产品推荐
相关产品推荐

