【问题标题】:How to return error response when database failed to commit数据库提交失败时如何返回错误响应
【发布时间】:2022-09-22 23:01:57
【问题描述】:

介绍:

在我们的 FastAPI 应用程序中,我们实现了用于提交数据库更改的依赖项(根据 https://fastapi.tiangolo.com/tutorial/dependencies/dependencies-with-yield/)。

问题:

我们面临的问题(在上面提供的网站上也部分提到)是即使提交没有成功,路由器响应也是 200。这仅仅是因为在我们的例子中,提交或回滚函数是在响应发送给请求者之后调用的。

例子:

数据库依赖:

def __with_db(request: Request):
    db = Session()
    try:
        yield db
        db.commit()
    except Exception as e:
        db.rollback()
        raise e
    finally:
        db.close()

作为端点示例,我们导入带有记录的 csv 文件,然后创建 db 模型实例,然后将它们添加到 db 会话中(为简单起见,删除了不相关的内容)。

from models import Movies
...
@router.post(\"/import\")
async def upload_movies(file: UploadFile, db: DbType = db_dependency):
    df = await read_csv(file)
    new_records = [Movies(**item) for item in df.to_dict(\"records\")]
    db.add_all(new_records)         # this is still valid operation, no error here

    return \"OK\"

端点内的所有内容都不会引发错误,因此端点会返回一个肯定的响应,但是,一旦执行了其余的依赖代码,它就会抛出一个错误(即,只要其中一条记录具有空值)。

问题:

当数据库未能提交更改时如何实际得到错误,有什么解决方案吗? 当然,最简单的方法是将db.commit() 甚至db.flush() 添加到每个端点,但由于我们有很多端点,我们希望避免在每个端点中重复(如果可能的话) .

此致,

  • 也许这 - FastAPI exception handler
  • 在提供的示例中,中间件尝试在await call_next(request) 上捕获错误,但棘手的部分是它不会在响应本身上捕获错误,因为在发送响应后出现数据库错误。

标签: python sqlalchemy fastapi


【解决方案1】:

我不知道你的 FastAPI 版本。但据我所知,从0.74.0 开始,与yield 的依赖关系可以在发送响应之前捕获HTTPException 和自定义异常(我测试0.80.0 没问题):

async def get_database():
    with Session() as session:
        try:
            yield session
        except HTTPException as e:
            session.rollback()
            raise e
        else:
            session.commit()
        finally:
            session.close()

如果提出了一个HTTPException,则流程为:
端点 -> 依赖捕获异常 -> ExceptionMiddleware 捕获异常 -> 响应

获取更多信息https://fastapi.tiangolo.com/release-notes/?h=asyncexi#breaking-changes_1

希望这是有用的。

【讨论】:

  • 首先,感谢您的回答。在您的示例中,您的依赖项中没有 session.commit() ,所以我想您必须在每个端点的末尾添加 session.commit() 才能在数据库中提交您的更改。在那种情况下它会正常工作,但在我的情况下,由于我们有很多端点,在分析任何其他更好的场景之前,我们不想在每个端点上添加同一条线。
  • @Barosh 我在 else 块中添加 session.commit()
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-23
  • 2018-10-04
  • 2021-01-08
  • 2021-04-20
  • 1970-01-01
  • 2018-01-21
相关资源
最近更新 更多