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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 20:05:08