首页 > 解决方案 > 将 PonyOrm 与 FastApi 一起使用的正确方法是什么?

问题描述

对于个人项目,我将 PonyOrm 与 FastApi 一起使用;有没有一种经典的方法可以在端点的整个异步生命周期调用中保持 db_session ?

PonyOrm 的文档中谈到了使用装饰器和产量;但它对我不起作用,所以在查看了其他 Github 项目之后,我发现这个解决方法工作正常。

但我真的不知道幕后发生了什么,以及为什么 Pony 的文档对异步主题不准确。

def _enter_session():
    session = db_session(sql_debug=True)
    Request.pony_session = session
    session.__enter__()


def _exit_session():
    session = getattr(Request, 'pony_session', None)
    if session is not None:
        session.__exit__()


@app.middleware("http")
async def add_pony(request: Request, call_next):
    _enter_session()
    response = await call_next(request)
    _exit_session()
    return response

然后在依赖项中,例如:

async def current_user(
        username: str = Depends(current_user_from_token)) -> User:

    with Request.pony_session:
        # db actions 

在端点调用中:

@router.post("/token", response_model=Token)
async def login_for_access_token(
        request: Request,
        user_agent: Optional[str] = Header(None),
        form_data: OAuth2PasswordRequestForm = Depends()):

    status: bool = authenticate_user(
        form_data.username,
        form_data.password,
        request.client.host,
        user_agent)


@db_session
def authenticate_user(
        username: str,
        password: str,
        client_ip: str = 'Undefined',
        client_app: str = 'Undefined'):
    user: User = User.get(email=username)

如果你们有更好的方法或好的解释,我很想听听:)

标签: python-asynciofastapiponyorm

解决方案


我有点像 PonyORM 开发人员和 FastAPI 用户。

async 和 Pony 的问题在于 Pony 使用我们理解的原子事务。此外,如果上下文将切换到另一个协程,我们还使用可以在另一个会话中使用的线程本地缓存。我同意我们应该在文档中添加有关它的信息。

为确保一切正常,您应该将其db_session用作上下文管理器,并确保在此代码块中没有异步调用。

如果您的端点不是异步的,您也可以db_session为它们使用装饰器。

在 Pony 中,我们同意在某些情况下使用ContextVar代替Local应该会有所帮助。

一句话的答案是:使用小的短期会话,不要用异步中断它们。


推荐阅读