- 一个文件结构示例
APIRouter- 导入
APIRouter - 使用
APIRouter的路径操作
- 导入
- 依赖项
- 其他使用
APIRouter的模块- 导入依赖项
- 相对导入如何工作
- 添加一些自定义的
tags、responses和dependencies
- 导入依赖项
FastAPI主体- 导入
FastAPI - 导入
APIRouter - 导入是如何工作的
- 避免名称冲突
- 包含
users和items的APIRouter - 包含一个有自定义
prefix、tags、responses和dependencies的APIRouter - 包含一个路径操作
- 导入
- 查看自动化的 API 文档
- 多次使用不同的
prefix包含同一个路由器 - 在另一个
APIRouter中包含一个APIRouter
如果你正在开发一个应用程序或 Web API,很少会将所有的内容都放在一个文件中。
FastAPI 提供了一个方便的工具,可以在保持所有灵活性的同时构建你的应用程序。
Info
如果你来自 Flask,那这将相当于 Flask 的 Blueprints。
一个文件结构示例
假设你的文件结构如下:
.
├── app
│ ├── __init__.py
│ ├── main.py
│ ├── dependencies.py
│ └── routers
│ │ ├── __init__.py
│ │ ├── items.py
│ │ └── users.py
│ └── internal
│ ├── __init__.py
│ └── admin.py
Tip
上面有几个 __init__.py 文件:每个目录或子目录中都有一个。
这就是能将代码从一个文件导入到另一个文件的原因。
例如,在 app/main.py 中,你可以有如下一行:
from app.routers import items
app目录包含了所有内容。并且它有一个空文件app/__init__.py,因此它是一个「Python 包」(「Python 模块」的集合):app。- 它包含一个
app/main.py文件。由于它位于一个 Python 包(一个包含__init__.py文件的目录)中,因此它是该包的一个「模块」:app.main。 - 还有一个
app/dependencies.py文件,就像app/main.py一样,它是一个「模块」:app.dependencies。 - 有一个子目录
app/routers/包含另一个__init__.py文件,因此它是一个「Python 子包」:app.routers。 - 文件
app/routers/items.py位于app/routers/包中,因此它是一个子模块:app.routers.items。 - 同样适用于
app/routers/users.py,它是另一个子模块:app.routers.users。 - 还有一个子目录
app/internal/包含另一个__init__.py文件,因此它是又一个「Python 子包」:app.internal。 app/internal/admin.py是另一个子模块:app.internal.admin。
带有注释的同一文件结构:
.
├──%20app%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20#%20「app」是一个%20Python%20包
│%20%20%20├──%20__init__.py%20%20%20%20%20%20#%20这个文件使「app」成为一个%20Python%20包
│%20%20%20├──%20main.py%20%20%20%20%20%20%20%20%20%20#%20「main」模块,例如%20import%20app.main
│%20%20%20├──%20dependencies.py%20%20#%20「dependencies」模块,例如%20import%20app.dependencies
│%20%20%20└──%20routers%20%20%20%20%20%20%20%20%20%20#%20「routers」是一个「Python%20子包」
│%20%20%20│%20%20%20├──%20__init__.py%20%20#%20使「routers」成为一个「Python%20子包」
│%20%20%20│%20%20%20├──%20items.py%20%20%20%20%20#%20「items」子模块,例如%20import%20app.routers.items
│%20%20%20│%20%20%20└──%20users.py%20%20%20%20%20#%20「users」子模块,例如%20import%20app.routers.users
│%20%20%20└──%20internal%20%20%20%20%20%20%20%20%20#%20「internal」是一个「Python%20子包」
│%20%20%20%20%20%20%20├──%20__init__.py%20%20#%20使「internal」成为一个「Python%20子包」
│%20%20%20%20%20%20%20└──%20admin.py%20%20%20%20%20#%20「admin」子模块,例如%20import%20app.internal.admin%20
APIRouter
假设专门用于处理用户逻辑的文件是位于%20/app/routers/users.py%20的子模块。
你希望将与用户相关的路径操作与其他代码分开,以使其井井有条。
但它仍然是同一%20FastAPI%20应用程序/web%20API%20的一部分(它是同一「Python%20包」的一部分)。
你可以使用%20APIRouter%20为该模块创建路径操作。
导入%20APIRouter
你可以导入它并通过与%20FastAPI%20类相同的方式创建一个「实例」:
app/routers/users.py
from%20fastapi%20import%20APIRouter%20router%20=%20APIRouter()%20@router.get("/users/",%20tags=["users"])async%20def%20read_users():%20%20%20%20return%20[{"username":%20"Rick"},%20{"username":%20"Morty"}]@router.get("/users/me",%20tags=["users"])async%20def%20read_user_me():%20%20%20%20return%20{"username":%20"fakecurrentuser"}@router.get("/users/{username}",%20tags=["users"])async%20def%20read_user(username:%20str):%20%20%20%20return%20{"username":%20username}
使用%20APIRouter%20的路径操作
然后你可以使用它来声明路径操作。
使用方式与%20FastAPI%20类相同:
app/routers/users.py
from%20fastapi%20import%20APIRouterrouter%20=%20APIRouter()@router.get("/users/",%20tags=["users"])%20async%20def%20read_users():%20%20%20%20return%20[{"username":%20"Rick"},%20{"username":%20"Morty"}]@router.get("/users/me",%20tags=["users"])%20async%20def%20read_user_me():%20%20%20%20return%20{"username":%20"fakecurrentuser"}@router.get("/users/{username}",%20tags=["users"])%20async%20def%20read_user(username:%20str):%20%20%20%20return%20{"username":%20username}
你可以将%20APIRouter%20视为一个「迷你%20FastAPI」类。
所有相同的选项都得到支持。
所有相同的%20parameters、responses、dependencies、tags%20等等。
Tip
在此示例中,该变量被命名为%20router,但你可以根据你的想法自由命名。
我们将在主%20FastAPI%20应用中包含该%20APIRouter,但首先,让我们来看看依赖项和另一个%20APIRouter。
依赖项
我们了解到我们将需要一些在应用程序的好几个地方所使用的依赖项。
因此,我们将它们放在它们自己的%20dependencies%20模块(app/dependencies.py)中。
现在我们将使用一个简单的依赖项来读取一个自定义的%20X-Token%20请求首部:
app/dependencies.py
from%20fastapi%20import%20Header,%20HTTPException%20async%20def%20get_token_header(x_token:%20str%20=%20Header()):%20if%20x_token%20!=%20"fake-super-secret-token":%20raise%20HTTPException(status_code=400,%20detail="X-Token%20header%20invalid")%20async%20def%20get_query_token(token:%20str):%20%20%20%20if%20token%20!=%20"jessica":%20%20%20%20%20%20%20%20raise%20HTTPException(status_code=400,%20detail="No%20Jessica%20token%20provided")
Tip
我们正在使用虚构的请求首部来简化此示例。
但在实际情况下,使用集成的安全性实用工具会得到更好的效果。
其他使用%20APIRouter%20的模块
假设你在位于%20app/routers/items.py%20的模块中还有专门用于处理应用程序中「项目」的端点。
你具有以下路径操作:
/items//items/{item_id}
这和%20app/routers/users.py%20的结构完全相同。
但是我们想变得更聪明并简化一些代码。
我们知道此模块中的所有路径操作都有相同的:
- 路径%20
prefix:/items。 tags:(仅有一个%20items%20标签)。- 额外的%20
responses。 dependencies:它们都需要我们创建的%20X-Token%20依赖项。
因此,我们可以将其添加到%20APIRouter%20中,而不是将其添加到每个路径操作中。
app/routers/items.py
from%20fastapi%20import%20APIRouter,%20Depends,%20HTTPExceptionfrom%20..dependencies%20import%20get_token_headerrouter%20=%20APIRouter(%20prefix="/items",%20tags=["items"],%20dependencies=[Depends(get_token_header)],%20responses={404:%20{"description":%20"Not%20found"}},%20)%20fake_items_db%20=%20{"plumbus":%20{"name":%20"Plumbus"},%20"gun":%20{"name":%20"Portal%20Gun"}}@router.get("/")%20async%20def%20read_items():%20%20%20%20return%20fake_items_db@router.get("/{item_id}")%20async%20def%20read_item(item_id:%20str):%20%20%20%20if%20item_id%20not%20in%20fake_items_db:%20%20%20%20%20%20%20%20raise%20HTTPException(status_code=404,%20detail="Item%20not%20found")%20%20%20%20return%20{"name":%20fake_items_db[item_id]["name"],%20"item_id":%20item_id}@router.put(%20%20%20%20"/{item_id}",%20%20%20%20tags=["custom"],%20%20%20%20responses={403:%20{"description":%20"Operation%20forbidden"}},)async%20def%20update_item(item_id:%20str):%20%20%20%20if%20item_id%20!=%20"plumbus":%20%20%20%20%20%20%20%20raise%20HTTPException(%20%20%20%20%20%20%20%20%20%20%20%20status_code=403,%20detail="You%20can%20only%20update%20the%20item:%20plumbus"%20%20%20%20%20%20%20%20)%20%20%20%20return%20{"item_id":%20item_id,%20"name":%20"The%20great%20Plumbus"}
由于每个路径操作的路径都必须以%20/%20开头,例如:
@router.get("/{item_id}")%20async%20def%20read_item(item_id:%20str):
%20%20%20%20...%20
…前缀不能以%20/%20作为结尾。
因此,本例中的前缀为%20/items。
我们还可以添加一个%20tags%20列表和额外的%20responses%20列表,这些参数将应用于此路由器中包含的所有路径操作。
我们可以添加一个%20dependencies%20列表,这些依赖项将被添加到路由器中的所有路径操作中,并将针对向它们发起的每个请求执行/解决。
Tip
请注意,和路径操作装饰器中的依赖项很类似,没有值会被传递给你的路径操作函数。
最终结果是项目相关的路径现在为:
/items//items/{item_id}
…如我们所愿。
- 它们将被标记为仅包含单个字符串%20
"items"%20的标签列表。- 这些「标签」对于自动化交互式文档系统(使用%20OpenAPI)特别有用。
- 所有的路径操作都将包含预定义的%20
responses。 - 所有的这些路径操作都将在自身之前计算/执行%20
dependencies%20列表。- 如果你还在一个具体的路径操作中声明了依赖项,它们也会被执行。
- 路由器的依赖项最先执行,然后是装饰器中的%20
dependencies,再然后是普通的参数依赖项。 - 你还可以添加具有%20
scopes%20的%20Security%20依赖项。
Tip
在%20APIRouter中具有%20dependencies%20可以用来,例如,对一整组的路径操作要求身份认证。即使这些依赖项并没有分别添加到每个路径操作中。
Check
prefix、tags、responses%20以及%20dependencies%20参数只是(和其他很多情况一样)FastAPI%20的一个用于帮助你避免代码重复的功能。
导入依赖项
这些代码位于%20app.routers.items%20模块,app/routers/items.py%20文件中。
我们需要从%20app.dependencies%20模块即%20app/dependencies.py%20文件中获取依赖函数。
因此,我们通过%20..%20对依赖项使用了相对导入:
app/routers/items.py
from%20fastapi%20import%20APIRouter,%20Depends,%20HTTPExceptionfrom%20..dependencies%20import%20get_token_header%20router%20=%20APIRouter(%20%20%20%20prefix="/items",%20%20%20%20tags=["items"],%20%20%20%20dependencies=[Depends(get_token_header)],%20%20%20%20responses={404:%20{"description":%20"Not%20found"}},)fake_items_db%20=%20{"plumbus":%20{"name":%20"Plumbus"},%20"gun":%20{"name":%20"Portal%20Gun"}}@router.get("/")async%20def%20read_items():%20%20%20%20return%20fake_items_db@router.get("/{item_id}")async%20def%20read_item(item_id:%20str):%20%20%20%20if%20item_id%20not%20in%20fake_items_db:%20%20%20%20%20%20%20%20raise%20HTTPException(status_code=404,%20detail="Item%20not%20found")%20%20%20%20return%20{"name":%20fake_items_db[item_id]["name"],%20"item_id":%20item_id}@router.put(%20%20%20%20"/{item_id}",%20%20%20%20tags=["custom"],%20%20%20%20responses={403:%20{"description":%20"Operation%20forbidden"}},)async%20def%20update_item(item_id:%20str):%20%20%20%20if%20item_id%20!=%20"plumbus":%20%20%20%20%20%20%20%20raise%20HTTPException(%20%20%20%20%20%20%20%20%20%20%20%20status_code=403,%20detail="You%20can%20only%20update%20the%20item:%20plumbus"%20%20%20%20%20%20%20%20)%20%20%20%20return%20{"item_id":%20item_id,%20"name":%20"The%20great%20Plumbus"}
相对导入如何工作
Tip
如果你完全了解导入的工作原理,请从下面的下一部分继续。
一个单点%20.,例如:
from%20.dependencies%20import%20get_token_header
表示:
- 从该模块(
app/routers/items.py%20文件)所在的同一个包(app/routers/%20目录)开始… - 找到%20
dependencies%20模块(一个位于%20app/routers/dependencies.py%20的虚构文件)… - 然后从中导入函数%20
get_token_header。
但是该文件并不存在,我们的依赖项位于%20app/dependencies.py%20文件中。
请记住我们的程序/文件结构是怎样的:
两个点%20..,例如:
from%20..dependencies%20import%20get_token_header
表示:
- 从该模块(
app/routers/items.py%20文件)所在的同一个包(app/routers/%20目录)开始… - 跳转到其父包(
app/%20目录)… - 在该父包中,找到%20
dependencies%20模块(位于%20app/dependencies.py%20的文件)… - 然后从中导入函数%20
get_token_header。
正常工作了!🎉
同样,如果我们使用了三个点%20...,例如:
from%20...dependencies%20import%20get_token_header
那将意味着:
- 从该模块(
app/routers/items.py%20文件)所在的同一个包(app/routers/%20目录)开始… - 跳转到其父包(
app/%20目录)… - 然后跳转到该包的父包(该父包并不存在,
app%20已经是最顶层的包%20😱)… - 在该父包中,找到%20
dependencies%20模块(位于%20app/%20更上一级目录中的%20dependencies.py%20文件)… - 然后从中导入函数%20
get_token_header。
这将引用%20app/%20的往上一级,带有其自己的%20__init%20__.py%20等文件的某个包。但是我们并没有这个包。因此,这将在我们的示例中引发错误。🚨
但是现在你知道了它的工作原理,因此无论它们多么复杂,你都可以在自己的应用程序中使用相对导入。🤓
添加一些自定义的%20tags、responses%20和%20dependencies
我们不打算在每个路径操作中添加前缀%20/items%20或%20tags%20=["items"],因为我们将它们添加到了%20APIRouter%20中。
但是我们仍然可以添加更多将会应用于特定的路径操作的%20tags,以及一些特定于该路径操作的额外%20responses:
app/routers/items.py
from%20fastapi%20import%20APIRouter,%20Depends,%20HTTPExceptionfrom%20..dependencies%20import%20get_token_headerrouter%20=%20APIRouter(%20%20%20%20prefix="/items",%20%20%20%20tags=["items"],%20%20%20%20dependencies=[Depends(get_token_header)],%20%20%20%20responses={404:%20{"description":%20"Not%20found"}},)fake_items_db%20=%20{"plumbus":%20{"name":%20"Plumbus"},%20"gun":%20{"name":%20"Portal%20Gun"}}@router.get("/")async%20def%20read_items():%20%20%20%20return%20fake_items_db@router.get("/{item_id}")async%20def%20read_item(item_id:%20str):%20%20%20%20if%20item_id%20not%20in%20fake_items_db:%20%20%20%20%20%20%20%20raise%20HTTPException(status_code=404,%20detail="Item%20not%20found")%20%20%20%20return%20{"name":%20fake_items_db[item_id]["name"],%20"item_id":%20item_id}@router.put(%20%20%20%20"/{item_id}",%20tags=["custom"],%20responses={403:%20{"description":%20"Operation%20forbidden"}},%20)async%20def%20update_item(item_id:%20str):%20%20%20%20if%20item_id%20!=%20"plumbus":%20%20%20%20%20%20%20%20raise%20HTTPException(%20%20%20%20%20%20%20%20%20%20%20%20status_code=403,%20detail="You%20can%20only%20update%20the%20item:%20plumbus"%20%20%20%20%20%20%20%20)%20%20%20%20return%20{"item_id":%20item_id,%20"name":%20"The%20great%20Plumbus"}
Tip
最后的这个路径操作将包含标签的组合:["items","custom"]。
并且在文档中也会有两个响应,一个用于%20404,一个用于%20403。
FastAPI%20主体
现在,让我们来看看位于%20app/main.py%20的模块。
在这里你导入并使用%20FastAPI%20类。
这将是你的应用程序中将所有内容联结在一起的主文件。
并且由于你的大部分逻辑现在都存在于其自己的特定模块中,因此主文件的内容将非常简单。
导入%20FastAPI
你可以像平常一样导入并创建一个%20FastAPI%20类。
我们甚至可以声明全局依赖项,它会和每个%20APIRouter%20的依赖项组合在一起:
app/main.py
from%20fastapi%20import%20Depends,%20FastAPI%20from%20.dependencies%20import%20get_query_token,%20get_token_header%20from%20.internal%20import%20adminfrom%20.routers%20import%20items,%20usersapp%20=%20FastAPI(dependencies=[Depends(get_query_token)])%20app.include_router(users.router)app.include_router(items.router)app.include_router(%20%20%20%20admin.router,%20%20%20%20prefix="/admin",%20%20%20%20tags=["admin"],%20%20%20%20dependencies=[Depends(get_token_header)],%20%20%20%20responses={418:%20{"description":%20"I'm%20a%20teapot"}},)@app.get("/")async%20def%20root():%20%20%20%20return%20{"message":%20"Hello%20Bigger%20Applications!"}
导入%20APIRouter
现在,我们导入具有%20APIRouter%20的其他子模块:
app/main.py
from%20fastapi%20import%20Depends,%20FastAPIfrom%20.dependencies%20import%20get_query_token,%20get_token_headerfrom%20.internal%20import%20adminfrom%20.routers%20import%20items,%20users%20app%20=%20FastAPI(dependencies=[Depends(get_query_token)])app.include_router(users.router)app.include_router(items.router)app.include_router(%20%20%20%20admin.router,%20%20%20%20prefix="/admin",%20%20%20%20tags=["admin"],%20%20%20%20dependencies=[Depends(get_token_header)],%20%20%20%20responses={418:%20{"description":%20"I'm%20a%20teapot"}},)@app.get("/")async%20def%20root():%20%20%20%20return%20{"message":%20"Hello%20Bigger%20Applications!"}
由于文件%20app/routers/users.py%20和%20app/routers/items.py%20是同一%20Python%20包%20app%20一个部分的子模块,因此我们可以使用单个点%20.%20通过「相对导入」来导入它们。
导入是如何工作的
这段代码:
from%20.routers%20import%20items,%20users
表示:
- 从该模块(
app/main.py%20文件)所在的同一个包(app/%20目录)开始… - 寻找%20
routers%20子包(位于%20app/routers/%20的目录)… - 从该包中,导入子模块%20
items%20(位于%20app/routers/items.py%20的文件)%20以及%20users%20(位于%20app/routers/users.py%20的文件)…
items%20模块将具有一个%20router%20变量(items.router)。这与我们在%20app/routers/items.py%20文件中创建的变量相同,它是一个%20APIRouter%20对象。
然后我们对%20users%20模块进行相同的操作。
我们也可以像这样导入它们:
from%20app.routers%20import%20items,%20users
Info
第一个版本是「相对导入」:
from%20.routers%20import%20items,%20users
第二个版本是「绝对导入」:
from%20app.routers%20import%20items,%20users
要了解有关%20Python%20包和模块的更多信息,请查阅关于%20Modules%20的%20Python%20官方文档。
避免名称冲突
我们将直接导入%20items%20子模块,而不是仅导入其%20router%20变量。
这是因为我们在%20users%20子模块中也有另一个名为%20router%20的变量。
如果我们一个接一个地导入,例如:
from%20.routers.items%20import%20routerfrom%20.routers.users%20import%20router
来自%20users%20的%20router%20将覆盖来自%20items%20中的%20router,我们将无法同时使用它们。
因此,为了能够在同一个文件中使用它们,我们直接导入子模块:
app/main.py
from%20fastapi%20import%20Depends,%20FastAPIfrom%20.dependencies%20import%20get_query_token,%20get_token_headerfrom%20.internal%20import%20adminfrom%20.routers%20import%20items,%20users%20app%20=%20FastAPI(dependencies=[Depends(get_query_token)])app.include_router(users.router)app.include_router(items.router)app.include_router(%20%20%20%20admin.router,%20%20%20%20prefix="/admin",%20%20%20%20tags=["admin"],%20%20%20%20dependencies=[Depends(get_token_header)],%20%20%20%20responses={418:%20{"description":%20"I'm%20a%20teapot"}},)@app.get("/")async%20def%20root():%20%20%20%20return%20{"message":%20"Hello%20Bigger%20Applications!"}
包含%20users%20和%20items%20的%20APIRouter
现在,让我们来包含来自%20users%20和%20items%20子模块的%20router。
app/main.py
from%20fastapi%20import%20Depends,%20FastAPIfrom%20.dependencies%20import%20get_query_token,%20get_token_headerfrom%20.internal%20import%20adminfrom%20.routers%20import%20items,%20usersapp%20=%20FastAPI(dependencies=[Depends(get_query_token)])app.include_router(users.router)%20app.include_router(items.router)%20app.include_router(%20%20%20%20admin.router,%20%20%20%20prefix="/admin",%20%20%20%20tags=["admin"],%20%20%20%20dependencies=[Depends(get_token_header)],%20%20%20%20responses={418:%20{"description":%20"I'm%20a%20teapot"}},)@app.get("/")async%20def%20root():%20%20%20%20return%20{"message":%20"Hello%20Bigger%20Applications!"}
users.router%20包含了%20app/routers/users.py%20文件中的%20APIRouter。
items.router%20包含了%20app/routers/items.py%20文件中的%20APIRouter。
使用%20app.include_router(),我们可以将每个%20APIRouter%20添加到主%20FastAPI%20应用程序中。
它将包含来自该路由器的所有路由作为其一部分。
实际上,它将在内部为声明在%20
APIRouter%20中的每个路径操作创建一个路径操作。
所以,在幕后,它实际上会像所有的东西都是同一个应用程序一样工作。
Check
包含路由器时,你不必担心性能问题。
这将花费几微秒时间,并且只会在启动时发生。
因此,它不会影响性能。⚡
包含一个有自定义%20prefix、tags、responses%20和%20dependencies%20的%20APIRouter
现在,假设你的组织为你提供了%20app/internal/admin.py%20文件。
它包含一个带有一些由你的组织在多个项目之间共享的管理员路径操作的%20APIRouter。
对于此示例,它将非常简单。但是假设由于它是与组织中的其他项目所共享的,因此我们无法对其进行修改,以及直接在%20APIRouter%20中添加%20prefix、dependencies、tags%20等:
app/internal/admin.py
from%20fastapi%20import%20APIRouterrouter%20=%20APIRouter()%20@router.post("/")async%20def%20update_admin():%20%20%20%20return%20{"message":%20"Admin%20getting%20schwifty"}
但是我们仍然希望在包含%20APIRouter%20时设置一个自定义的%20prefix,以便其所有路径操作以%20/admin%20开头,我们希望使用本项目已经有的%20dependencies%20保护它,并且我们希望它包含自定义的%20tags%20和%20responses。
我们可以通过将这些参数传递给%20app.include_router()%20来完成所有的声明,而不必修改原始的%20APIRouter:
app/main.py
from%20fastapi%20import%20Depends,%20FastAPIfrom%20.dependencies%20import%20get_query_token,%20get_token_headerfrom%20.internal%20import%20adminfrom%20.routers%20import%20items,%20usersapp%20=%20FastAPI(dependencies=[Depends(get_query_token)])app.include_router(users.router)app.include_router(items.router)app.include_router(%20%20%20%20admin.router,%20prefix="/admin",%20tags=["admin"],%20dependencies=[Depends(get_token_header)],%20responses={418:%20{"description":%20"I'm%20a%20teapot"}},%20)@app.get("/")async%20def%20root():%20%20%20%20return%20{"message":%20"Hello%20Bigger%20Applications!"}
这样,原始的%20APIRouter%20将保持不变,因此我们仍然可以与组织中的其他项目共享相同的%20app/internal/admin.py%20文件。
结果是在我们的应用程序中,来自%20admin%20模块的每个路径操作都将具有:
/admin%20前缀%20。admin%20标签。get_token_header%20依赖项。418%20响应。%20🍵
但这只会影响我们应用中的%20APIRouter,而不会影响使用它的任何其他代码。
因此,举例来说,其他项目能够以不同的身份认证方法使用相同的%20APIRouter。
包含一个路径操作
我们还可以直接将路径操作添加到%20FastAPI%20应用中。
这里我们这样做了…只是为了表明我们可以做到🤷:
app/main.py
from%20fastapi%20import%20Depends,%20FastAPIfrom%20.dependencies%20import%20get_query_token,%20get_token_headerfrom%20.internal%20import%20adminfrom%20.routers%20import%20items,%20usersapp%20=%20FastAPI(dependencies=[Depends(get_query_token)])app.include_router(users.router)app.include_router(items.router)app.include_router(%20%20%20%20admin.router,%20%20%20%20prefix="/admin",%20%20%20%20tags=["admin"],%20%20%20%20dependencies=[Depends(get_token_header)],%20%20%20%20responses={418:%20{"description":%20"I'm%20a%20teapot"}},)@app.get("/")%20async%20def%20root():%20return%20{"message":%20"Hello%20Bigger%20Applications!"}
它将与通过%20app.include_router()%20添加的所有其他路径操作一起正常运行。
特别的技术细节
注意:这是一个非常技术性的细节,你也许可以直接跳过。
APIRouter%20没有被「挂载」,它们与应用程序的其余部分没有隔离。
这是因为我们想要在%20OpenAPI%20模式和用户界面中包含它们的路径操作。
由于我们不能仅仅隔离它们并独立于其余部分来「挂载」它们,因此路径操作是被「克隆的」(重新创建),而不是直接包含。
查看自动化的%20API%20文档
现在,使用%20app.main%20模块和%20app%20变量运行%20uvicorn:
fast%20→uvicorn%20app.main:app%20—reload
然后打开位于%20http://127.0.0.1:8000/docs%20的文档。
你将看到使用了正确路径(和前缀)和正确标签的自动化%20API%20文档,包括了来自所有子模块的路径:
多次使用不同的 prefix 包含同一个路由器
你也可以在同一路由器上使用不同的前缀来多次使用 .include_router()。
在有些场景这可能有用,例如以不同的前缀公开同一个的 API,比方说 /api/v1 和 /api/latest。
这是一个你可能并不真正需要的高级用法,但万一你有需要了就能够用上。
在另一个 APIRouter 中包含一个 APIRouter
与在 FastAPI 应用程序中包含 APIRouter 的方式相同,你也可以在另一个 APIRouter 中包含 APIRouter,通过:
router.include_router(other_router)
请确保在你将 router 包含到 FastAPI 应用程序之前进行此操作,以便 other_router 中的路径操作也能被包含进来。
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。









评论