FastAPI 路由配置全解析:从基础到高级应用

FastAPI 作为现代 Python Web 框架的代表,以其高性能、类型安全和自动文档而闻名。其中,路由配置是构建 API 服务的核心环节。本文将深入探讨 FastAPI 路由的各种配置方式,从基础用法到高级技巧,帮助你构建清晰、可维护的 API 接口

一、基础路由配置

FastAPI 使用装饰器语法定义路由,简洁直观:

from fastapi import FastAPI

app = FastAPI()

# 基本 GET 请求
@app.get("/")
def read_root():
    return {"Hello": "World"}

# 带路径参数的路由
@app.get("/items/{item_id}")
def read_item(item_id: int, q: str | None = None):
    return {"item_id": item_id, "q": q}

# 带查询参数的路由
@app.get("/users/{user_id}/items/{item_id}")
def read_user_item(
    user_id: int, item_id: str, short: bool = False
):
    item = {"item_id": item_id, "owner_id": user_id}
    if not short:
        item.update(
            {"description": "This is an amazing item that has a long description"}
        )
    return item

二、请求方法与路径参数

FastAPI 支持所有 HTTP 请求方法:GET、POST、PUT、DELETE、OPTIONS、HEAD、PATCH、TRACE

# POST 请求处理
@app.post("/items/")
def create_item(item: Item):
    return item

# PUT 请求处理
@app.put("/items/{item_id}")
def update_item(item_id: int, item: Item):
    return {"item_id": item_id, **item.dict()}

# DELETE 请求处理
@app.delete("/items/{item_id}")
def delete_item(item_id: int):
    return {"item_id": item_id, "status": "deleted"}

三、请求体与输入验证

使用 Pydantic 模型定义请求体,自动完成数据验证和序列化:

from pydantic import BaseModel

class Item(BaseModel):
    name: str
    price: float
    is_offer: bool | None = None

@app.post("/items/")
def create_item(item: Item):
    item_dict = item.dict()
    if item.tax:
        price_with_tax = item.price + item.tax
        item_dict.update({"price_with_tax": price_with_tax})
    return item_dict

四、路径操作配置

为路由添加额外配置,如标签、摘要、描述和响应模型:

@app.get(
    "/items/{item_id}",
    response_model=Item,
    tags=["items"],
    summary="Get an item by ID",
    description="Get details of a specific item by its unique identifier.",
    response_description="The requested item",
)
def read_item(item_id: int):
    return items_db.get(item_id)

五、依赖注入系统

FastAPI 的依赖注入机制在路由配置中也发挥着重要作用。依赖注入可以帮助我们在处理路由请求时,方便地获取所需的资源,如数据库连接、认证信息等。例如,我们要在处理用户请求时验证用户的身份,可以定义一个依赖函数:

from fastapi import Depends, FastAPI

def verify_token(token: str):
    # 这里进行实际的token验证逻辑
    if token == "valid_token":
        return True
    return False

app = FastAPI()

@app.get("/protected/users/")
def read_protected_users(is_valid: bool = Depends(verify_token)):
    if is_valid:
        return {"message": "You have access to protected users"}
    return {"message": "Access denied"}

在上述代码中,verify_token函数是一个依赖函数,它接收一个token参数并进行验证。在read_protected_users路由处理函数中,通过Depends(verify_token)verify_token函数作为依赖注入。只有当verify_token函数返回True时,客户端才能访问到相应的资源

六、路由分组与 APIRouter

当 API 项目逐渐变大,路由数量增多时,对路由进行分组管理会使代码更加清晰和易于维护。FastAPI 通过APIRouter类实现路由分组。例如,我们可以将用户相关的路由和商品相关的路由分别分组

from fastapi import APIRouter

# 创建用户路由
user_router = APIRouter(
    prefix="/users",
    tags=["users"],
    responses={404: {"description": "Not found"}},
)

@user_router.get("/")
def read_users():
    return [{"username": "Rick"}, {"username": "Morty"}]

@user_router.get("/{username}")
def read_user(username: str):
    return {"username": username}

# 将路由添加到应用
app.include_router(user_router)

在这个示例中,首先创建了一个APIRouter实例user_router,设置了前缀(prefix)、标签(tags)、响应(responses)。前缀用于在路由路径前添加统一的路径,标签则可用于 API 文档的分类展示。然后,在各自的路由中定义具体的路由处理函数。最后,通过app.include_router()方法将分组路由添加到主应用app中

七、高级路由技巧

1、路径操作装饰器参数:

@app.get(
    "/items/{item_id}",
    response_model=Item,
    status_code=status.HTTP_200_OK,
    deprecated=True,  # 标记为弃用
)

2、路径操作顺序:

FastAPI 按定义顺序匹配路由,特殊路径需优先定义:

@app.get("/users/me")
def read_user_me():
    return {"user_id": "the current user"}

@app.get("/users/{user_id}")
def read_user(user_id: str):
    return {"user_id": user_id}

3、路由的响应处理

FastAPI 支持对路由的响应进行灵活配置,包括响应状态码、响应模型等。例如,我们可以通过status_code参数指定响应的状态码,通过response_model参数指定响应的数据模型:

from fastapi import FastAPI
from pydantic import BaseModel

class User(BaseModel):
    name: str
    age: int

app = FastAPI()

@app.post("/users/", response_model=User, status_code=201)
def create_user(user: User):
    return user

在这个例子中,定义了一个User数据模型,它继承自BaseModel。在create_user路由处理函数中,通过response_model=User指定响应的数据将按照User模型进行序列化,status_code=201指定创建用户成功后返回的状态码为201 Created

八、错误处理与异常

自定义异常处理器,统一错误响应格式:

from fastapi import Request
from fastapi.responses import JSONResponse

@app.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
    return JSONResponse(
        status_code=exc.status_code,
        content={"detail": exc.detail, "request_url": str(request.url)},
    )

九、实战案例:

项目结构

apps/
  ├── app01/
  │   └── urls.py  # 购物中心相关接口
  ├── app02/
  │   └── urls.py  # 用户中心相关接口
  └── main.py      # 主应用入口

这种结构的优势在于高内聚、低耦合:

  • 不同功能模块(如用户系统、业务系统)的路由可以独立维护
  • 便于团队协作开发,减少代码冲突
  • 支持微服务架构下的服务拆分

路由模块实现

app01/urls.py - 购物中心接口

# /apps/app01/urls.py
from fastapi import APIRouter  
  
app01 = APIRouter()  
  
@app01.get('/food')  
def get_food():  
    return {'shop':'food'}  
  
@app01.get('/bed')  
def get_bed():  
    return {'shop':'bed'}
  • 创建了一个名为app01的路由组
  • 定义了两个接口:

    • GET /food 返回食品商店信息
    • GET /bed 返回床品商店信息

app02/urls.py - 用户中心接口

# /apps/app02/urls.py
from fastapi import APIRouter  
  
app02 = APIRouter()  
  
@app02.get('/login')  
def user_login():  
    return {'user':'login'}  
  
@app02.get('/reg')  
def user_reg():  
    return {'user':'reg'}
  • 创建了一个名为app02的路由组
  • 定义了两个接口:

    • GET /login 返回用户登录信息
    • GET /reg 返回用户注册信息

主应用集成

main.py - 应用入口

# /apps/main.py
from fastapi import FastAPI  
import uvicorn  
from apps.app01.urls import app01  
from apps.app02.urls import app02  
  
app = FastAPI()  
  
app.include_router(app01, prefix='/shop', tags=['购物中心接口'])  
app.include_router(app02, prefix='/user', tags=['用户中心接口'])  
  
if __name__ == '__main__':  
    uvicorn.run('main:app',port=8080,reload=True)
  • 创建 FastAPI 应用实例
  • 通过include_router方法挂载两个路由组:

    • app01 挂载到 /shop 前缀下,标签为 "购物中心接口"
    • app02 挂载到 /user 前缀下,标签为 "用户中心接口"
  • 使用 Uvicorn 运行应用,监听 8080 端口,并开启热重载(开发模式)

最终生成的 API 路径

原路径挂载后路径标签
/food/shop/food购物中心接口
/bed/shop/bed购物中心接口
/login/user/login用户中心接口
/reg/user/reg/login用户中心接口

这种设计的优势:

  1. 清晰的功能边界:不同业务模块的接口一目了然
  2. 自动生成文档:FastAPI 会根据标签自动分组生成 Swagger/ReDoc 文档
  3. 便于版本控制:可以为不同版本的 API 设置独立前缀(如v1、v2)
最后修改:2025 年 06 月 05 日
如果觉得我的文章对你有用,请随意赞赏