Skip to content

第 07 章 路由 Router ​

学习目标 ​

学完本章,你应该能:

  1. 理解路由的作用,掌握 RESTful API 规范
  2. 掌握 fba 的路由目录结构和注册方式
  3. 能自己定义并注册一个接口

一、路由是什么 ​

路由(Router) 是"URL 地址"和"处理函数"之间的映射。它决定了:当用户访问某个 URL 时,应该调用哪个函数来处理。

比如:

GET  /api/v1/user/1     → 查询用户1
POST /api/v1/user       → 创建用户
PUT  /api/v1/user/1     → 更新用户1
DELETE /api/v1/user/1   → 删除用户1

fba 的路由遵循 RESTful API 规范。

RESTful:一种 API 设计风格,用 HTTP 方法(GET/POST/PUT/DELETE)表达对资源的操作,URL 用名词表示资源。

URL 与函数的映射关系 ​

二、路由目录结构 ​

fba 的路由结构很规范,分为两种情况:

情况 1:业务含子包(如 admin) ​

backend/app/admin/
├── api/
│   └── v1/
│       ├── sys/
│       │   ├── user/
│       │   │   ├── __init__.py   # 注册子包内所有路由
│       │   │   └── user.py       # 定义具体接口
│       │   └── ...
│       ├── __init__.py
│       └── router.py             # 注册所有子包的路由

情况 2:业务不含子包 ​

backend/app/xxx/
├── api/
│   └── v1/
│       ├── __init__.py
│       ├── xxx.py                # 定义具体接口
│       └── router.py             # 注册所有路由

三、定义接口(APIRouter) ​

fba 用 FastAPI 的 APIRouter 来组织路由。一个典型的接口文件:

python
from fastapi import APIRouter

router = APIRouter()


@router.get('/{user_id}', summary='获取用户详情')
async def get_user(user_id: int):
    ...

关键点:

  • 路由变量统一命名为 router(这是 fba 的约定)
  • 每个接口用 summary 参数写清楚功能,方便生成文档

四、注册路由(重点:导入方式) ​

fba 有一个非常重要的约定:注册路由时的导入方式。

因为所有路由变量都叫 router,导入时必须用 as 起别名避免冲突:

python
from backend.app.admin.api.v1.sys.user import router as user_router

在 router.py 中统一注册:

python
from fastapi import APIRouter

from backend.app.admin.api.v1.sys.user import router as user_router

v1 = APIRouter()

v1.include_router(user_router, prefix='/users', tags=['用户管理'])

记住:务必用 import router as xxx_router 的方式导入,这是 fba 的路由铁律。

五、路由层级关系 ​

fba 的路由是多层嵌套的,最终拼成完整的 URL:

顶级 router(backend/app/router.py)
   └── admin 的 router(app/admin/router.py)
       └── v1 的 router(api/v1/router.py)
           └── sys 的 router(api/v1/sys/__init__.py)
               └── user 的 router(user.py 里的具体接口)

每一层都可以加 prefix(路径前缀),最终拼出类似 /api/v1/admin/sys/user/1 的完整路径。

路由层级与 URL 拼接 ​

六、常见 HTTP 方法 ​

方法用途对应操作
GET查询Read
POST新增Create
PUT / PATCH更新Update
DELETE删除Delete

七、完整示例:用户接口 ​

python
# backend/app/admin/api/v1/sys/user.py
from fastapi import APIRouter

from backend.app.admin.schema.user import CreateUserParam, GetUserDetail
from backend.common.response.response_model import ResponseModel

router = APIRouter()


@router.get('/{user_id}', summary='获取用户详情', response_model=ResponseModel)
async def get_user(user_id: int):
    # 这里调用 service 层
    return response_base.success(data={'id': user_id})


@router.post('', summary='创建用户')
async def create_user(obj: CreateUserParam):
    return response_base.success()

八、常见疑问 ​

Q1:为什么要统一命名为 router? 为了规范一致,看到 router 就知道这是路由对象,减少理解成本。代价是导入时要起别名。

Q2:prefix 和路由装饰器里的路径是什么关系? 最终 URL = 所有层级的 prefix 拼接 + 装饰器里的路径。比如 prefix='/users' + @router.get('/{id}') = /users/{id}。

本章小结 ​

关键要点回顾:

  • 路由是 URL 到处理函数的映射,遵循 RESTful 规范
  • 路由变量统一命名为 router
  • 注册时必须 import router as xxx_router 起别名
  • 路由多层嵌套,通过 prefix 拼路径
  • 每个接口写 summary 说明功能

下一步: 路由定义好了,但真正的逻辑在 Service 和 CRUD 层,第 08 章深入讲解。


对应官方文档:路由(backend/reference/router.html)