You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

FastAPI使用APIRouter时如何正确处理MongoDB连接?

解决FastAPI拆分应用后路由无法访问数据库连接的问题

你的错误原因很明确:你把MongoDB的连接实例挂载到了app对象上,但你在路由文件里试图从APIRouter对象(也就是router)上去访问Admin属性,这两个对象完全独立,自然会报AttributeError。下面是几种靠谱的解决方式,按推荐程度排序:

方法一:使用FastAPI依赖注入(官方推荐)

这种方式符合FastAPI的设计理念,解耦性最好,也方便后续测试。

  1. 主文件中定义获取数据库连接的依赖函数:
# 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)
  1. 在路由文件中通过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实例,进而访问挂载的数据库连接:

  1. 主文件里把数据库连接放到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"]
  1. 路由文件里注入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

方法三:全局数据库对象(适合小型项目)

这种方式最简单,但耦合性高,不适合大型项目的长期维护:

  1. 新建db.py文件,定义全局变量:
# db.py
admin_db = None
  1. 主文件启动时给全局变量赋值:
# 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"]
  1. 路由文件直接导入全局变量使用:
# 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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 09:20:24