likes
comments
collection
share

FastAPI 工程化模块路由 - APIRouter

作者站长头像
站长
· 阅读数 26

前言

在构建中大型应用时,推荐使用 FastAPI 的 APIRouter 来组织路由,而不是直接在视图函数上使用装饰器。这是因为当业务功能和接口数量增多时,使用装饰器来组织路由会显得分散且难以维护。相比之下,APIRouter 提供了更好的模块化管理方式,使代码结构更加清晰和易于维护。

通过 APIRouter,我们可以将相关的路由和业务逻辑分组,放在各自的模块中,方便团队协作开发和维护。这不仅提高了代码的可读性,还使得应用的扩展变得更加简单和灵活。

官方文档参考链接:FastAPI 官方文档 - Bigger Applications with Multiple Files

接下来,我们将通过一个 Demo 展示如何在 FastAPI 中使用 APIRouter 进行模块化路由管理。

工程目录

FastAPI 工程化模块路由 - APIRouter

├── api_router_demo    项目名称
├── handlers           路由处理模块
│   ├── __init__.py
│   ├── book.py
│   ├── movie.py
│   └── user.py
├── routers            路由模块
│   ├── __init__.py
│   ├── book.py
│   ├── movie.py
│   └── user.py
└── server.py          应用服务模块

应用主入口

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author: Hui
# @File: server.py
# @Desc: { 应用服务模块 }
# @Date: 2024/06/28 11:35
import uvicorn
from fastapi import FastAPI
from contextlib import asynccontextmanager
from routers import api_router


@asynccontextmanager
async def lifespan(app: FastAPI):
    await startup()
    yield
    await shutdown()


app = FastAPI(lifespan=lifespan, description="APIRouter模块路由Demo")
# app = FastAPI(lifespan=lifespan, routes=api_router.routes, description="APIRouter模块路由Demo")


async def startup():
    # 初始化路由
    app.include_router(api_router)
    
    # 初始化资源...


async def shutdown():
    print("释放资源")
    print("Shutting down...")


def main():
    uvicorn.run(app)


if __name__ == '__main__':
    main()

主入口就简单的通过 app.include_router(api_router) 初始化一些路由资源

也可以构造FastAPI应用时入参指定

app = FastAPI(lifespan=lifespan, routes=api_router.routes, description="APIRouter模块路由Demo")

具体路由信息在 routers 包下

路由模块

用户模块路由

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author: Hui
# @File: user.py
# @Desc: { 用户模块路由 }
# @Date: 2024/06/28 11:47
from fastapi import APIRouter
from handlers import UserHandler

user_router = APIRouter()

user_router.add_api_route(
    "/api/v1/users/register", UserHandler.register, methods=["POST"], summary="用户注册"
)
user_router.add_api_route(
    "/api/v1/users/login", UserHandler.login, methods=["POST"], summary="用户登陆"
)
user_router.add_api_route(
    "/api/v1/users", UserHandler.get_users, methods=["GET"], summary="获取用户列表"
)
user_router.add_api_route(
    "/api/v1/users/{user_id}", UserHandler.get_user_detail, methods=["GET"], summary="用户详情"
)

图书模块路由

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author: Hui
# @File: book.py
# @Desc: { 书籍模块路由 }
# @Date: 2024/06/28 11:48
from fastapi import APIRouter
from handlers import BookHandler

book_router = APIRouter()

book_router.add_api_route(
    "/api/v1/books", BookHandler.get_books, methods=["GET"], summary="获取图书列表"
)
book_router.add_api_route(
    "/api/v1/books/{book_id}", BookHandler.get_book_detail, methods=["GET"], summary="图书详情"
)

电影模块路由

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author: Hui
# @File: movie.py
# @Desc: { 电影模块路由 }
# @Date: 2024/06/28 11:48
from fastapi import APIRouter
from handlers import MovieHandler

movie_router = APIRouter()

movie_router.add_api_route(
    "/api/v1/movies", MovieHandler.get_movies, methods=["GET"], summary="获取电影列表"
)
movie_router.add_api_route(
    "/api/v1/movies/{movie_id}", MovieHandler.get_movie_detail, methods=["GET"], summary="电影详情"
)

不同模块各自组织路由,就是通过 APIRouter 的 add_api_route 方法来添加路由信息,常用参数如下

  • path 路由路径

  • endpoint 对应路由处理函数

  • methods 路由请求方法列表

  • response_model 响应数据模型(pydantic的model)

  • summary 路由备注

  • ...

这里为了方便如何组织模块路由,一些请求模型、响应模型入参没有指定。

然后再 routers 下的 __init__ 模块将各模块路由串联起来

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author: Hui
# @File: __init__.py.py
# @Desc: { 项目路由初始化模块 }
# @Date: 2024/06/28 11:47
from fastapi import APIRouter
from .book import book_router
from .user import user_router
from .movie import movie_router

api_router = APIRouter()

api_router.include_router(user_router, tags=["用户模块"])
api_router.include_router(book_router, tags=["图书模块"])
api_router.include_router(movie_router, tags=["电影模块"])

使用 APIRouter 的 include_router 方法进行套娃串联路由,可以指定一些路由前缀、路由模块tags标记等信息,我一开始写项目的喜欢指定一些路由前缀 /api/v1/users 等,这样在写代码的时候可以少写,但实际使用上我抓包获取的接口路由发现定位代码的时候不方便,因为路由路径是组合到一起的,全局搜不到,就不能快速定位,于是还是取消了前缀。如下就是指定前缀的方式

api_router = APIRouter(prefix="/api/v1")

api_router.include_router(user_router, prefix="/users", tags=["用户模块"])
api_router.include_router(book_router, prefix="/books", tags=["图书模块"])
api_router.include_router(movie_router, prefix="/movies", tags=["电影模块"])

路由处理模块

图书模块handler

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author: Hui
# @File: book.py
# @Desc: { 图书模块handler }
# @Date: 2024/06/28 11:58

class BookHandler:
    @classmethod
    async def get_books(cls, book_name: str):
        """获取图书列表"""
        # 参数校验
        # 调用业务层处理
        # 响应出参
        return "获取图书列表"

    @classmethod
    async def get_book_detail(cls, book_id: int):
        return "获取图书详情"

电影模块handler

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author: Hui
# @File: movie.py
# @Desc: { 电影模块handler }
# @Date: 2024/06/28 11:58


class MovieHandler:
    @classmethod
    async def get_movies(cls, movie_name: str, movie_type: str):
        """获取电影列表"""
        # 参数校验
        # 调用业务层处理
        # 响应出参
        return "获取电影列表"

    @classmethod
    async def get_movie_detail(cls, movie_id: int):
        return "获取电影详情"

用户模块handler

#!/usr/bin/python3
# -*- coding: utf-8 -*-
# @Author: Hui
# @File: user.py
# @Desc: { 用户模块handler }
# @Date: 2024/06/28 11:58


class UserHandler:

    @classmethod
    async def register(cls, username: str, password: str):
        return "用户注册"

    @classmethod
    async def login(cls, username: str, password: str):
        return "用户登录"

    @classmethod
    async def get_user_detail(cls, user_id: int):
        return "获取用户详情"

    @classmethod
    async def get_users(cls, username: str):
        """获取用户列表"""
        # 参数校验
        # 调用业务层处理
        # 响应出参
        return "获取用户列表"

handler 其实就是路由视图函数,这层的作用主要就是进行如下处理

  • 参数校验
  • 调用业务层(service)处理
  • 响应出参

路由API展示

直接访问 http://127.0.0.1:8000/docs#/ 就可以查看路由接口文档

FastAPI 工程化模块路由 - APIRouter

fastapi还是很方便的将代码路由结构组织好了,api接口文档也生成了,如果在线的接口文档用的不方便可以直接导入到APIFOX 中是使用。

源代码

Github:FastAPI 实战手册

从FastAPI的安装、请求处理、响应返回等基础知识入手,到中间件、数据库操作、身份认证等核心组件的应用,再到实战项目的开发,以及源码分析,循序渐进地介绍FastAPI的使用,旨在让读者全面掌握这个框架。

转载自:https://juejin.cn/post/7385350484410761242
评论
请登录