【Python开发】FastAPI 11:构建多文件应用

目录

1 APIRouter

1.1 APIRouter 使用

1.2 其他模块的引入

2 app 项目示例

2.1 文件结构

2.2 其他 文件

2.3 main 文件

2.4 API 文档


📌 源码地址:

https://gitee.com/yinyuu/fast-api_study_yinyu

1 APIRouter

大家可以看到,前边的示例均是以 app = FastAPI() 作为路由,但是它只适合小项目,如果接口按模块进行划分就不满足了。而 APIRouter 正实现了接口按模块的功能,以使其井井有条。

1.1 APIRouter 使用

类似 app = FastAPI()

from fastapi import APIRouter #导入 APIRouterrouter = APIRouter()@router.get("/users/", tags=["users"])
async def read_users():return [{"username": "Rick"}, {"username": "Morty"}]

可以将 APIRouter 视为一个小号 FastAPI 类,所有相同的选项都得到支持,比如 parameters、responses、dependencies、tags 等等。

1.2 其他模块的引入

类似 FastAPI ,我们还可以通过 prefixtagsdependencies responses 等参数来减少重复代码和增加效率。比如有两个接口:

  • /items/
  • /items/{item_id}

他们的路径前缀一样,那么我们通过以下方式简化代码:

  • prefix:/items,前缀,不能以 / 作为结尾,不然回合路径重合
  • tags:items 标签,主要在 api 文档中用于分类
  • responses:额外的响应模型,所有接口都将拥有
  • dependencies:依赖,比如 get_token_header 依赖项。
from fastapi import APIRouter, Depends, HTTPExceptionfrom ..dependencies import get_token_header #通过 .. 对依赖项使用了相对导入,具体代码可看第二章router = APIRouter(prefix="/items",tags=["items"],dependencies=[Depends(get_token_header)],responses={404: {"description": "Not found"}},
)@router.get("/")
async def read_items():return fake_items_db@router.get("/{item_id}")
async def read_item(item_id: str):if item_id not in fake_items_db:raise HTTPException(status_code=404, detail="Item not found")return {"name": fake_items_db[item_id]["name"], "item_id": item_id}

最终结果是项目相关的路径现在为:

  • /items/
  • /items/{item_id}

2 app 项目示例

接下来以 app 项目为例,展示一下多文件应用的构建。

2.1 文件结构

📌 结构如下:

app 目录包含了所有内容,他是一个 Python 包:

  • app/main.pymain 模块,也是项目的主文件,或者说启动类
  • app/dependencies.py:存放依赖项
  • app/routers/ :Python 子包:
    • app/routers/items.py:存放 ietms 相关接口
    • app/routers/users.py:存放 users 相关接口
  • app/internal/ :Python 子包:
    • app/internal/admin.py:内管相关接口

2.2 其他 文件

📌 dependencies.py

依赖项相关方法,验证请求体和 token ~

from fastapi import Header, HTTPExceptionasync 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")async def get_query_token(token: str):if token != "jessica":raise HTTPException(status_code=400, detail="No Jessica token provided")

📌 items.py

from fastapi import APIRouter, Depends, HTTPExceptionfrom ..dependencies import get_token_headerrouter = APIRouter(prefix="/items",tags=["items"],dependencies=[Depends(get_token_header)],responses={404: {"description": "Not found111"}},
)fake_items_db = {"plumbus": {"name": "Plumbus"}, "gun": {"name": "Portal Gun"}}@router.get("/")
async def read_items():return fake_items_db@router.get("/{item_id}")
async def read_item(item_id: str):if item_id not in fake_items_db:raise HTTPException(status_code=404, detail="Item not found")return {"name": fake_items_db[item_id]["name"], "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 != "plumbus":raise HTTPException(status_code=403, detail="You can only update the item: plumbus")return {"item_id": item_id, "name": "The great Plumbus"}

📌 users.py

from fastapi import APIRouterrouter = APIRouter()@router.get("/users/", tags=["users"])
async def read_users():return [{"username": "Rick"}, {"username": "Morty"}]@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}

📌 users.py

from fastapi import APIRouterrouter = APIRouter()@router.post("/")
async def update_admin():return {"message": "Admin getting schwifty"}

以上接口文件均使用 APIRouter ,最后将调用给 main 文件以供汇总。

2.3 main 文件

这里你导入并使用 FastAPI 类,是应用程序中将所有内容联结在一起的主文件。 

from fastapi import Depends, FastAPIfrom .dependencies import get_query_token, get_token_header
from .internal import admin
from .routers import items, usersapp = FastAPI(dependencies=[Depends(get_query_token)])app.include_router(users.router)
app.include_router(items.router)
app.include_router( #依旧可自定义参数admin.router,prefix="/admin",tags=["admin"],dependencies=[Depends(get_token_header)],responses={418: {"description": "I'm a teapot"}},
)@app.get("/")
async def root():return {"message": "Hello Bigger Applications!"}if __name__ == '__main__':import uvicornuvicorn.run(app, host="127.0.0.1", port=8000)

📌 导入模块

比如:

from .routers import items, users
  • 这表示从该模块(app/main.py 文件)所在的同一个包(app/ 目录)
  • 寻找 routers 子包(位于 app/routers/ 的目录)...
  • 从该包中,导入子模块 items (位于 app/routers/items.py 的文件) 以及 users (位于 app/routers/users.py 的文件)...

items 模块将具有一个 router 变量(items.router)。

📌 app.include_router

app.include_router(users.router)
app.include_router(items.router)

使用 app.include_router(),我们可以将每个 APIRouter 添加到主 FastAPI 应用程序中。 它将包含来自该路由器的所有路由作为其一部分。

2.4 API 文档

启动 main 文件,访问 http://127.0.0.1:8000/docs,即可看到使用了正确路径(和前缀)和正确标签的自动化 API 文档,包括了来自所有子模块的路径:

本文链接:https://my.lmcjl.com/post/9608.html

展开阅读全文

4 评论

留下您的评论.