FastAPI+Starlette-Admin删除文件条目触发SQLAlchemy会话错误求助
解决方案
1. 重写Starlette-Admin删除逻辑,手动管控会话与异常
Starlette-Admin默认删除流程未处理文件存储异常,会导致SQLAlchemy会话状态紊乱。你需要自定义模型视图的delete方法,手动处理文件删除、数据库操作,并捕获ObjectDoesNotExistError。
示例代码:
from starlette_admin.contrib.sqladmin import ModelView from starlette.responses import JSONResponse from starlette.exceptions import HTTPException from libcloud.storage.types import ObjectDoesNotExistError # 替换为你的实际模块引用 from your_app.models import TargetModel from your_app.storage import storage_driver from your_app.database import get_db_session class TargetModelAdmin(ModelView): model = TargetModel async def delete(self, request, pk): session = get_db_session() try: # 查询待删除的数据库对象 db_obj = session.query(TargetModel).get(pk) if not db_obj: return JSONResponse(status_code=404, detail="对象不存在") # 处理文件删除,捕获文件不存在异常 try: # 替换为你的CustomFile实际删除逻辑 storage_driver.delete_object(db_obj.file_path) except ObjectDoesNotExistError: # 文件不存在时不中断,继续执行数据库删除 pass # 删除数据库条目并提交会话 session.delete(db_obj) session.commit() return JSONResponse(status_code=200, detail="删除成功") except Exception as e: # 仅在会话活跃时执行回滚,避免状态冲突 if session.is_active: session.rollback() raise HTTPException(status_code=500, detail=f"删除失败: {str(e)}") finally: # 手动关闭会话,清除状态残留 session.close()
2. 调整操作顺序,优先处理文件异常
将文件删除逻辑放在数据库删除之前,通过捕获ObjectDoesNotExistError确保流程不中断,避免会话因异常进入不可用状态。
3. 校验会话生命周期配置
确保FastAPI的SQLAlchemy会话中间件配置正确,保证每个请求的会话独立:
from sqlalchemy import create_engine from sqlalchemy.orm import sessionmaker, scoped_session engine = create_engine("你的数据库连接URL") SessionLocal = scoped_session(sessionmaker(autocommit=False, autoflush=False, bind=engine)) # 会话依赖项 def get_db(): db = SessionLocal() try: yield db finally: db.close()
问题根源复盘
删除操作触发ObjectDoesNotExistError时,Starlette-Admin默认错误处理会尝试回滚已处于committed状态的会话,导致SQLAlchemy抛出InvalidRequestError。通过手动接管删除流程、捕获文件存储异常,可确保会话状态始终可控。
内容的提问来源于stack exchange,提问作者Avin Mathew
相关产品推荐
相关产品推荐

