如何在带有 FastAPI 的嵌套路由器中包含路径参数?

Hen*_*mas 3 python fastapi

如何将一个包含APIRouter在另一个中并指定某个路径参数是必需的前缀?

\n

对于上下文:\n假设我有组织和用户的概念。一个用户只属于一个组织。我的网络应用程序的结构如下:

\n
\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 web_app\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 endpoints\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py # produces main_router by including other routers inside each other\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 organization.py # contains endpoints relevant to the organization\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 user.py # contains endpoints relevant to the user\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.py # includes main_router in app\n
Run Code Online (Sandbox Code Playgroud)\n

假设我想为组织和用户实现基本的 CRUD 功能。我的端点可能看起来像这样:

\n

对于组织:

\n
GET /api/latest/org/{org_id}\nPOST /api/latest/org/{org_id}\nPUT /api/latest/org/{org_id}\nDELETE /api/latest/org/{org_id}\n
Run Code Online (Sandbox Code Playgroud)\n

对于用户:

\n
GET /api/latest/org/{org_id}/users/{user_id}\nPOST /api/latest/org/{org_id}/users/{user_id}\nPUT /api/latest/org/{org_id}/users/{user_id}\nDELETE /api/latest/org/{org_id}/users/{user_id}\n
Run Code Online (Sandbox Code Playgroud)\n

由于用户嵌套在 orgs 下,因此user.py可以像这样编写所有端点:

\n
\xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 web_app\n    \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 endpoints\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 __init__.py # produces main_router by including other routers inside each other\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 organization.py # contains endpoints relevant to the organization\n        \xe2\x94\x9c\xe2\x94\x80\xe2\x94\x80 user.py # contains endpoints relevant to the user\n    \xe2\x94\x94\xe2\x94\x80\xe2\x94\x80 main.py # includes main_router in app\n
Run Code Online (Sandbox Code Playgroud)\n

但这很快就会变得很恶心。user_router与 完全脱节,尽管一个org_router应该嵌套在另一个之中。如果我对组织路由器进行更改,我现在需要更改每个用户路由器端点。上帝禁止我在用户下嵌套一些东西......

\n

所以根据我的问题,我希望这样的事情能起作用:

\n
GET /api/latest/org/{org_id}\nPOST /api/latest/org/{org_id}\nPUT /api/latest/org/{org_id}\nDELETE /api/latest/org/{org_id}\n
Run Code Online (Sandbox Code Playgroud)\n
# __init__.py\norg_router.include_router(user_router)\nmain_router = APIRouter(prefix="/api/latest/")\nmain_router.include_router(org_router)\n
Run Code Online (Sandbox Code Playgroud)\n

但这给了我以下错误:\n AssertionError: Path params must be of one of the supported types{org_id}如果我从前缀中删除,我不会收到错误,所以我知道APIRouter(prefix="/org/{org_id}/users")问题所在。

\n

这是我们从 FastAPI 获得的关于此事的唯一文档:https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-in-another

\n

我正在寻找的东西可能吗?这似乎是一种极其常见的情况,所以我很好奇其他人是怎么做的。

\n

Dje*_*eth 5

我不确定您为什么会收到此错误,但您所请求的事情(在APIRoute前缀中使用路径参数)绝对是可能的。当您将 包含到APIRoute应用程序实例中时,它将评估所有路由并将它们从专用路由附加到APIRouteAPIRoute. 后者始终存在于app = FastAPI()应用程序对象中。路径参数本身根据请求进行解析。

下面是一个完整的工作示例,它将按原样运行:

from fastapi import APIRouter, FastAPI

app = FastAPI()


@app.get("/")
async def root():
    return {"hello": "world"}


router = APIRouter(prefix="/org/{org_id}")


@router.get("/users/{user_id}")
def get_user(org_id: int, user_id: int):
    return {"org": org_id, "user:": user_id}


app.include_router(router)

if __name__ == "__main__":
    import uvicorn

    uvicorn.run(app, host="0.0.0.0", port=8000)
Run Code Online (Sandbox Code Playgroud)

我们可以使用curl检查结果:

% curl localhost:8000/org/1/users/2
{"org":1,"user:":2}%
Run Code Online (Sandbox Code Playgroud)