zoukankan      html  css  js  c++  java
  • FastAPI(40)- 大型应用程序的项目拆分

    背景

    • 假设要搭建一个测试平台,那么整个项目的 API 数量肯定很多个,他们不可能放在同一个文件中
    • FastAPI 提供了一个方便的工具来构建应用程序,同时保持所有的灵活性

    项目架构

    假设结构如下

    .
    ├── app
    │   ├── __init__.py
    │   ├── main.py
    │   ├── dependencies.py
    │   └── routers
    │   │   ├── __init__.py
    │   │   ├── items.py
    │   │   └── users.py
    │   └── internal
    │       ├── __init__.py
    │       └── admin.py
    • main:应用程序的主入口,会添加所有子路由
    • dependencies:存放应用程序要用到的依赖项
    • routers:子路由,根据模块划分,比如 users 存放用户信息相关的路由,items 存放其他内容的路由
    • internal:一些公共路由

    APIRouter

    有点像 Flask 里面的蓝图,为某个模块创建路径操作

    users.py 代码

    #!usr/bin/env python
    # -*- coding:utf-8 _*-
    """
    # author: 小菠萝测试笔记
    # blog:  https://www.cnblogs.com/poloyy/
    # time: 2021/9/28 7:26 下午
    # file: users.py
    """
    
    from fastapi import APIRouter, Depends, HTTPException
    from dependencies import get_token_header
    
    # 属于该模块的路由
    user_router = APIRouter(
        # 这里配置的 tags、dependencies、responses 对这个模块的内的所有路径操作都生效
        # 路径前缀,该模块下所有路径操作的前缀
        prefix="/users",
        # 标签
        tags=["users"],
        # 依赖项
        dependencies=[Depends(get_token_header)],
        # 响应
        responses={404: {"description": "users Not found"}}
    )
    
    
    @user_router.get('/account/login')
    async def login():
        return {}
    
    
    @user_router.get('/account/logout')
    async def logout():
        return {}
    
    
    # 单独给某个路径操作声明 tags、responses
    @user_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"}

    items.py 代码

    #!usr/bin/env python
    # -*- coding:utf-8 _*-
    """
    # author: 小菠萝测试笔记
    # blog:  https://www.cnblogs.com/poloyy/
    # time: 2021/9/28 7:26 下午
    # file: items.py
    """
    
    from fastapi import APIRouter, Depends
    from dependencies import get_token_header
    
    item_router = APIRouter(
        # 这里配置的 tags、dependencies、responses 对这个模块的内的所有路径操作都生效
        # 路径前缀,该模块下所有路径操作的前缀
        prefix="/items",
        # 标签
        tags=["items"],
        # 依赖项
        dependencies=[Depends(get_token_header)],
        # 响应
        responses={404: {"description": "items Not found"}}
    )
    
    
    @item_router.get('/item')
    async def index():
        return {}
    
    
    @item_router.get('/item/list')
    async def list():
        return {}

    routers/__init__.py

    from .items import item_router
    from .users import user_router

    admin.py

    #!usr/bin/env python
    # -*- coding:utf-8 _*-
    """
    # author: 小菠萝测试笔记
    # blog:  https://www.cnblogs.com/poloyy/
    # time: 2021/9/28 7:26 下午
    # file: admin.py
    """
    
    from fastapi import APIRouter
    
    admin_router = APIRouter()
    
    
    @admin_router.post("/")
    async def update_admin():
        return {"message": "Admin getting schwifty"}

    common/__init__.py

    from .admin import admin_router

    main.py

    #!usr/bin/env python
    # -*- coding:utf-8 _*-
    """
    # author: 小菠萝测试笔记
    # blog:  https://www.cnblogs.com/poloyy/
    # time: 2021/9/28 7:25 下午
    # file: main.py
    """
    import uvicorn
    from fastapi import FastAPI, Depends
    
    # 导入子路由
    from dependencies import get_query_token, get_token_header
    from routers import user_router, item_router
    from common import admin_router
    
    # 主路由
    app = FastAPI(
        # 声明全局依赖项
        # 如果每个 APIRouter 都会用到这个依赖项,那么应该声明为全局依赖项
        dependencies=[Depends(get_query_token)]
    )
    
    # 添加子路由
    app.include_router(user_router)
    app.include_router(item_router)
    # 也可以在这里给子路由声明 prefix、tags、dependencies、responses,而无需修改原始的 APIRouter
    app.include_router(
        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__":
        uvicorn.run(app="main:app", host="127.0.0.1", port=8080, debug=True, reload=True)

    重点

    • 使用 app.include_router() 可以将每个 APIRouter 添加到主 FastAPI 应用程序中,它将包括来自该路由器的所有路由作为它的一部分
    • 它实际上会在内部为 APIRouter 中声明的每个路径操作创建一个路径操作,因此,在幕后,它实际上会像所有东西都是同一个应用程序一样工作
    • 使用 app.include_router() 时,不必担心性能,只需要几微秒,并且只会在启动时发生,所以不会影响性能

    主程序-子路由的架构图

    • 这个架构还是比较简单的,主程序直接包含子路由
    • 但其实子路由还可以再包含一个子路由
    • 个人把主程序也称为主路由(感觉更好理解)
    user_router = APIRouter(
        prefix="/users",
    )
    
    user_router.include_router(
        router=item_router
        prefix="/items"
    )

    FastAPI() 的 include_router() 源码

  • 相关阅读:
    SCOM 初探 [SCOM应用系列之一]
    SCOM 安装部署 [SCOM应用系列之二]
    CMMI 配置管理(Configuration Management)系列(1) 简介
    设计模式总结之创建型设计模式
    tabbar图片渲染的问题
    react实现自定义hooks(节流和防抖)
    前端工程化5js源码编译和ast
    react实现自定义hooks(跑马灯)
    react实现自定义hooks(倒计时)
    react实现自定义hooks(移动端拖拽)
  • 原文地址:https://www.cnblogs.com/poloyy/p/15350578.html
Copyright © 2011-2022 走看看