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

FastAPI存储数据库连接至app.state报错:AttributeError: 'State'无'db'属性

问题:FastAPI中无法在路由中访问app.state.db,报错AttributeError: 'State' object has no attribute 'db'

近期遇到如下错误:

AttributeError: 'State' object has no attribute 'db'

尝试将MongoDB连接存储到app.state.db并在不同路由中使用,但访问失败。相关代码如下:

db.py

from motor.motor_asyncio import AsyncIOMotorClient
from decouple import config

async def get_mongo_connection():
    client = AsyncIOMotorClient(config('MONGO_URL'))
    db = client[config('MONGO_DB')]
    return db

app.py

from utilities.conn.mongo import get_mongo_connection

@app.on_event("startup")
@version(1, 0)
async def startup_event():
    app.state.db = await get_mongo_connection()

routes.py

from fastapi import APIRouter, Depends, HTTPException, Request
from fastapi_versioning import VersionedFastAPI, version


router = APIRouter(
    tags=["Account"],
    dependencies=[]
)

@router.post("/send-otp")
@version(1,0)
async def send_otp(request : Request, input : SendOTP):
    print(request.app.state.db)
    return {}

请问如何修复该错误,或是否有更好的方法在所有路由中使用数据库连接?


解决方案

错误根源

你使用fastapi-versioning的VersionedFastAPI包装了原始FastAPI应用,但startup事件是绑定在原始app上的。包装后的新app并不会继承原始app的state属性,导致路由中访问request.app.state.db时找不到对应的属性。

修复方案1:修正startup事件绑定位置

如果要继续用app.state存储连接,需要把startup事件绑定到包装后的版本化app上,而非原始app。修改app.py:

from fastapi import FastAPI
from fastapi_versioning import VersionedFastAPI
from utilities.conn.mongo import get_mongo_connection
from routes import router

# 创建原始应用实例
app = FastAPI()
app.include_router(router)

# 生成版本化应用
versioned_app = VersionedFastAPI(app)

# 给版本化应用绑定启动事件
@versioned_app.on_event("startup")
async def startup_event():
    versioned_app.state.db = await get_mongo_connection()

修改后,路由中访问request.app.state.db就能获取到正确的数据库连接。

修复方案2:使用依赖注入(推荐)

FastAPI官方推荐用依赖注入管理全局资源,这种方式能避免版本化包装带来的state问题,同时代码更清晰、可测试。

步骤1:创建数据库依赖函数

在db.py中添加依赖逻辑:

from motor.motor_asyncio import AsyncIOMotorClient
from decouple import config
from fastapi import Depends

# 全局存储客户端实例,避免重复创建连接
_client = None

async def get_mongo_db():
    global _client
    if _client is None:
        _client = AsyncIOMotorClient(config('MONGO_URL'))
    db = _client[config('MONGO_DB')]
    yield db

步骤2:在路由中注入依赖

修改routes.py:

from fastapi import APIRouter, Depends
from fastapi_versioning import version
from utilities.conn.mongo import get_mongo_db
from pydantic import BaseModel

# 定义请求模型(若未定义)
class SendOTP(BaseModel):
    # 按需添加字段,例如:
    phone: str

router = APIRouter(
    tags=["Account"],
    dependencies=[]
)

@router.post("/send-otp")
@version(1,0)
async def send_otp(input : SendOTP, db = Depends(get_mongo_db)):
    # 直接使用注入的db实例
    print(db)
    # 示例:查询集合
    # user = await db.users.find_one({"phone": input.phone})
    return {}

可选步骤:处理连接关闭

如果需要在应用 shutdown 时关闭MongoDB连接,在app.py中添加事件:

from utilities.conn.mongo import _client

@versioned_app.on_event("shutdown")
async def shutdown_event():
    if _client is not None:
        _client.close()

这种方式的优势:

  • 无需依赖request.app.state,彻底规避版本化包装的兼容问题
  • 符合FastAPI设计规范,代码可读性、可维护性更强
  • 方便在多个路由、模块中复用数据库连接

内容的提问来源于stack exchange,提问作者harsh_jain100

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 10:32:46