FAST API 多次包含同一路由器,不同 prefix


 

如果要構建應用程序或Web API,則很少將所有內容都放在一個文件中。

FastAPI提供了一種方便的工具,可在保持所有靈活性的同時構建應用程序。

信息

如果您來自Flask,那將相當於Flask的藍圖。

示例文件結構

假設您的文件結構如下:

.
├── app
│   ├── __init__.py
│   ├── main.py
│   └── routers
│       ├── __init__.py
│       ├── items.py
│       └── users.py

小費

有兩個__init__.py文件:每個目錄或子目錄一個。

這就是允許將代碼從一個文件導入另一個文件的原因。

例如,app/main.py您可以輸入以下內容:

from app.routers import items
  • app目錄包含所有內容。
  • app目錄有一個空文件app/__init__.py
    • 因此,該app目錄是“ Python包”(“ Python模塊”的集合)。
  • app目錄還有一個app/main.py文件。
    • 由於它位於Python軟件包目錄中(因為存在一個文件__init__.py),因此它是該軟件包的“模塊”:app.main
  • 有一個子目錄app/routers/
  • 子目錄app/routers也有一個空文件__init__.py
    • 因此,它是一個“ Python子包”。
  • 該文件app/routers/items.py在旁邊app/routers/__init__.py
    • 因此,這是一個子模塊:app.routers.items
  • 該文件app/routers/users.py在旁邊app/routers/__init__.py
    • 因此,這是一個子模塊:app.routers.users

APIRouter

假設專門用於處理用戶的文件是的子模塊/app/routers/users.py

您希望將與用戶相關路徑操作與其余代碼分開,以使其井井有條。

但是它仍然是同一FastAPI應用程序/ Web API的一部分(它是同一“ Python包”的一部分)。

您可以使用來為該模塊創建路徑操作APIRouter

進口 APIRouter

您可以導入它,並使用與該類相同的方式創建一個“實例” FastAPI

from fastapi import APIRouter router = APIRouter() @router.get("/users/", tags=["users"]) async def read_users(): return [{"username": "Foo"}, {"username": "Bar"}] @router.get("/users/me", tags=["users"]) async def read_user_me(): return {"username": "fakecurrentuser"} @router.get("/users/{username}", tags=["users"]) async def read_user(username: str): return {"username": username} 

路徑操作APIRouter

然后使用它聲明路徑操作

以與使用FastAPI相同的方式使用它

from fastapi import APIRouter router = APIRouter() @router.get("/users/", tags=["users"]) async def read_users(): return [{"username": "Foo"}, {"username": "Bar"}] @router.get("/users/me", tags=["users"]) async def read_user_me(): return {"username": "fakecurrentuser"} @router.get("/users/{username}", tags=["users"]) async def read_user(username: str): return {"username": username} 

您可以將其APIRouter視為“迷你FastAPI”類。

支持所有相同的選項。

所有相同的參數,響應,依賴性,標簽等。

小費

在此示例中,變量稱為router,但是您可以根據需要命名。

我們將把它包含APIrouter在主FastAPI應用程序中,但首先,讓我們添加另一個APIRouter

另一個模塊 APIRouter

假設您在的模塊中還具有專用於處理應用程序中“項目”的端點app/routers/items.py

您具有以下路徑操作

  • /items/
  • /items/{item_id}

與的結構相同app/routers/users.py

但是,可以說這一次我們比較懶。

而且我們不需要在每個路徑操作中都顯式地鍵入/items/鍵入(稍后將能夠進行操作):tags=["items"]

from fastapi import APIRouter, HTTPException router = APIRouter() @router.get("/") async def read_items(): return [{"name": "Item Foo"}, {"name": "item Bar"}] @router.get("/{item_id}") async def read_item(item_id: str): return {"name": "Fake Specific Item", "item_id": item_id} @router.put( "/{item_id}", tags=["custom"], responses={403: {"description": "Operation forbidden"}}, ) async def update_item(item_id: str): if item_id != "foo": raise HTTPException(status_code=403, detail="You can only update the item: foo") return {"item_id": item_id, "name": "The Fighters"} 

添加一些自定義的tagsresponsesdependencies

我們既不添加前綴/items/也不在tags=["items"]以后添加它們。

但是,我們可以添加自定義tagsresponses將被應用到特定的路徑操作

from fastapi import APIRouter, HTTPException router = APIRouter() @router.get("/") async def read_items(): return [{"name": "Item Foo"}, {"name": "item Bar"}] @router.get("/{item_id}") async def read_item(item_id: str): return {"name": "Fake Specific Item", "item_id": item_id} @router.put( "/{item_id}",  tags=["custom"],  responses={403: {"description": "Operation forbidden"}}, ) async def update_item(item_id: str): if item_id != "foo": raise HTTPException(status_code=403, detail="You can only update the item: foo") return {"item_id": item_id, "name": "The Fighters"} 

主要的 FastAPI

現在,讓我們在中查看模塊app/main.py

在這里導入和使用類FastAPI

這將是應用程序中將所有內容捆綁在一起的主文件。

進口 FastAPI

您可以像平常一樣導入和創建一個FastAPI類:

from fastapi import Depends, FastAPI, Header, HTTPException from .routers import items, users app = FastAPI() async def get_token_header(x_token: str = Header(...)): if x_token != "fake-super-secret-token": raise HTTPException(status_code=400, detail="X-Token header invalid") app.include_router(users.router) app.include_router( items.router, prefix="/items", tags=["items"], dependencies=[Depends(get_token_header)], responses={404: {"description": "Not found"}}, ) 

導入 APIRouter

但是這次我們沒有直接在中添加路徑操作FastAPI app

我們導入其他具有APIRouters的子模塊

from fastapi import Depends, FastAPI, Header, HTTPException from .routers import items, users app = FastAPI() async def get_token_header(x_token: str = Header(...)): if x_token != "fake-super-secret-token": raise HTTPException(status_code=400, detail="X-Token header invalid") app.include_router(users.router) app.include_router( items.router, prefix="/items", tags=["items"], dependencies=[Depends(get_token_header)], responses={404: {"description": "Not found"}}, ) 

由於該文件app/routers/items.py是同一Python包的一部分,因此我們可以使用“點符號”將其導入。

匯入的運作方式

這部分:

from .routers import items, users 

手段:

  • 從此模塊(文件app/main.py)所在的相同包(目錄app/)開始...
  • 尋找子包routers(目錄位於app/routers/)...
  • 然后從中導入子模塊items(位於的文件app/routers/items.py)和users(位於的文件app/routers/users.py)...

該模塊items將具有一個變量routeritems.router)。這與我們在文件中創建的相同app/routers/items.py這是一個APIRouter模塊也一樣users

我們也可以像這樣導入它們:

from app.routers import items, users 

信息

第一個版本是“相對導入”。

第二個版本是“絕對導入”。

要了解有關Python包和模塊的更多信息,請閱讀有關Modules的官方Python文檔

避免名稱沖突

我們將items直接導入子模塊,而不是僅導入其變量router

這是因為我們router在子模塊中還有另一個變量users

如果我們一個接一個地導入,例如:

from .routers.items import router from .routers.users import router 

routerusers將覆蓋從一個items,我們將無法在同一時間使用它們。

因此,為了能夠在同一個文件中使用它們,我們直接導入子模塊:

from fastapi import Depends, FastAPI, Header, HTTPException from .routers import items, users app = FastAPI() async def get_token_header(x_token: str = Header(...)): if x_token != "fake-super-secret-token": raise HTTPException(status_code=400, detail="X-Token header invalid") app.include_router(users.router) app.include_router( items.router, prefix="/items", tags=["items"], dependencies=[Depends(get_token_header)], responses={404: {"description": "Not found"}}, ) 

包括一個 APIRouter

現在,包括router子模塊中的users

from fastapi import Depends, FastAPI, Header, HTTPException from .routers import items, users app = FastAPI() async def get_token_header(x_token: str = Header(...)): if x_token != "fake-super-secret-token": raise HTTPException(status_code=400, detail="X-Token header invalid") app.include_router(users.router) app.include_router( items.router, prefix="/items", tags=["items"], dependencies=[Depends(get_token_header)], responses={404: {"description": "Not found"}}, ) 

信息

users.router包含APIRouter文件內部app/routers/users.py

隨着app.include_router()我們可以添加APIRouter到主FastAPI應用程序。

它將包括來自該路由器的所有路由作為其一部分。

技術細節

實際上,它將為內部聲明的每個路徑操作內部創建一個路徑操作APIRouter

因此,在幕后,它實際上將像一切都是同一單個應用程序一樣工作。

校驗

包括路由器時,您不必擔心性能。

這將需要幾微秒,並且只會在啟動時發生。

因此,它不會影響性能。

包括APIRouterprefixtagsresponses,和dependencies

現在,讓我們包括items子模塊中的路由器

但是,請記住,我們很懶,沒有對所有路徑操作添加/items/也不添加嗎?tags

我們可以添加一個前綴的所有路徑操作使用參數prefixapp.include_router()

由於每個路徑操作的路徑都必須以開頭/,例如:

@router.get("/{item_id}") async def read_item(item_id: str): ... 

...前綴不得包含final /

因此,在這種情況下,前綴為/items

我們還可以添加一個列表,tags列表將應用於此路由器中包括的所有路徑操作

並且我們可以添加預定義responses,該預定義也將包含在所有路徑操作中

我們可以添加一個列表,dependencies列表將被添加到路由器中的所有路徑操作中,並將針對對它們的每個請求執行/解決。請注意,就像路徑操作修飾符中的依賴項一樣,任何值都不會傳遞給路徑操作function

from fastapi import Depends, FastAPI, Header, HTTPException from .routers import items, users app = FastAPI() async def get_token_header(x_token: str = Header(...)):  if x_token != "fake-super-secret-token":  raise HTTPException(status_code=400, detail="X-Token header invalid") app.include_router(users.router) app.include_router(  items.router,  prefix="/items",  tags=["items"],  dependencies=[Depends(get_token_header)],  responses={404: {"description": "Not found"}}, ) 

最終結果是項目路徑現在為:

  • /items/
  • /items/{item_id}

...按照我們的意圖。

  • 它們將被標記為包含單個字符串的標簽列表"items"
  • 聲明了標簽路徑操作"custom"將同時包含標簽itemscustom
    • 這些“標簽”對於自動交互式文檔系統(使用OpenAPI)特別有用。
  • 所有這些都將包括預定義的responses
  • 聲明自定義響應路徑操作403將同時具有預定義的響應(404)和403聲明中聲明。
  • 所有這些路徑操作將在其dependencies之前具有評估/執行的列表
    • 如果您還在特定的路徑操作中聲明依賴項它們也將被執行
    • 首先執行路由器相關性,然后dependencies在裝飾器中執行,然后執行常規參數相關性。
    • 您還可以使用添加Security依賴項scopes

小費

dependencies一個裝飾都可以使用,例如,要求身份驗證整組的路徑操作即使沒有將依賴項單獨添加到每個依賴項中。

校驗

prefixtagsresponsesdependencies參數(如在許多其他情況下),從僅僅是一種功能FastAPI來幫助你避免代碼重復。

小費

您也可以直接添加路徑操作,例如使用:@app.get(...)

除了app.include_router(),在同一個FastAPI應用中。

它仍然可以正常工作。

非常技術細節

注意:這是一個非常技術性的細節,您可能可以跳過


所述APIRouters的不是“安裝”,它們不從應用程序的其余部分隔離。

這是因為我們希望將它們的路徑操作包括在OpenAPI架構和用戶界面中。

由於我們不能僅僅隔離它們並獨立於其余部分來“裝載”它們,因此路徑操作被“克隆”(重新創建),而不是直接包含在內。

檢查自動API文檔

現在,運行uvicorn,使用模塊app.main和變量app

uvicorn app.main:app --reload
信息:在http://127.0.0.1:8000上運行的Uvicorn(按CTRL + C退出)

restart↻

然后在http://127.0.0.1:8000/docs中打開文檔

您將看到使用正確的路徑(和前綴)和正確的標記的自動API文檔,包括來自所有子模塊的路徑:

多次包含同一路由器,不同 prefix

您也可以.include_router()同一路由器上使用不同的前綴多次使用。

例如,這可以用於以不同的前綴(例如/api/v1和)公開相同的API /api/latest

這是您可能真正不需要的高級用法,但是如果您有需要,可以使用。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM