我如何将一个APIRouter
包含在另一个中,并指定某些路径param是必需的前缀?
对于上下文:假设我有组织和用户的概念。用户只属于一个组织。我的网络应用程序的结构如下:
├── web_app
├── endpoints
├── __init__.py # produces main_router by including other routers inside each other
├── organization.py # contains endpoints relevant to the organization
├── user.py # contains endpoints relevant to the user
└── main.py # includes main_router in app
让我们假设我希望为组织和用户实现基本的CRUD功能。我的端点看起来可能是这样的:
对于orgs:
GET /api/latest/org/{org_id}
POST /api/latest/org/{org_id}
PUT /api/latest/org/{org_id}
DELETE /api/latest/org/{org_id}
供用户使用:
GET /api/latest/org/{org_id}/users/{user_id}
POST /api/latest/org/{org_id}/users/{user_id}
PUT /api/latest/org/{org_id}/users/{user_id}
DELETE /api/latest/org/{org_id}/users/{user_id}
由于用户是嵌套在orgs下的,所以在user.py
中,我可以编写如下所示的所有端点:
user_router = APIRouter()
@user_router.get("/org/{org_id}/users/{user_id}")
async def get_user(org_id, user_id):
...
但很快就会恶心起来。user_router
与org_router
完全脱节,即使其中一个应该嵌套在另一个内部。如果我对组织路由器进行了更改,现在我需要更改每个用户路由器端点。上帝禁止我在用户下面有嵌套的东西..。
所以,根据我的问题,我希望像这样的东西能起作用:
# user.py
user_router = APIRouter(prefix="/org/{org_id}/users")
@user_router.get("/{user_id}")
async def get_user(org_id, user_id):
# __init__.py
org_router.include_router(user_router)
main_router = APIRouter(prefix="/api/latest/")
main_router.include_router(org_router)
但这给了我以下错误:AssertionError: Path params must be of one of the supported types
。如果从前缀中删除{org_id}
,我就不会得到错误,所以我知道APIRouter(prefix="/org/{org_id}/users")
是问题所在。
这是我们从FastAPI获得的关于这个问题的唯一文档:https://fastapi.tiangolo.com/tutorial/bigger-applications/#include-an-apirouter-in-another
我要找的东西有可能吗?这似乎是一种非常普遍的情况,所以我很好奇其他人做什么。
发布于 2022-08-18 06:03:25
我不知道您为什么会收到这个错误,但是您请求的东西(使用APIRoute
前缀中的路径参数)是绝对可能的。当您将APIRoute
包含到应用实例中时,它将评估所有路由,并将它们从专用的APIRoute
添加到主APIRoute
。后者总是出现在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)
我们可以用卷曲检查结果:
% curl localhost:8000/org/1/users/2
{"org":1,"user:":2}%
https://stackoverflow.com/questions/73396611
复制相似问题