FastAPI 基本路由(手把手讲解)

更新时间:

💡一则或许对你有用的小广告

欢迎加入小哈的星球 ,你将获得:专属的项目实战 / 1v1 提问 / Java 学习路线 / 学习打卡 / 每月赠书 / 社群讨论

截止目前, 星球 内专栏累计输出 90w+ 字,讲解图 3441+ 张,还在持续爆肝中.. 后续还会上新更多项目,目标是将 Java 领域典型的项目都整一波,如秒杀系统, 在线商城, IM 即时通讯,权限管理,Spring Cloud Alibaba 微服务等等,已有 3100+ 小伙伴加入学习 ,欢迎点击围观

前言

在现代 Web 开发领域,FastAPI 因其高性能、易维护性和丰富的类型注解支持,逐渐成为构建 API 的热门选择。而路由(Routing)作为 API 的核心组成部分,决定了客户端请求如何被分发到对应的处理函数。本文将从零开始,深入讲解 FastAPI 基本路由 的设计原理、实现方法和常见场景,帮助开发者快速掌握这一关键技能。无论是编程新手还是有一定经验的开发者,都能通过本文建立对路由系统的清晰认知。


一、基础路由的构建:从第一个示例开始

1.1 什么是路由?

可以将路由理解为“交通导航系统”:当客户端(如浏览器或第三方程序)向服务器发起请求时,路由系统会根据请求的路径(Path)和方法(Method)将请求导向对应的处理函数。例如,访问 /api/users 的 GET 请求会触发获取用户列表的逻辑,而 POST 请求则可能创建新用户。

1.2 快速上手:第一个 FastAPI 路由

安装 FastAPI 并运行一个最简单的示例:

from fastapi import FastAPI  
app = FastAPI()  

@app.get("/")  
async def read_root():  
    return {"message": "Hello World"}  

执行 uvicorn main:app --reload 后,访问 http://localhost:8000,即可看到返回的 JSON 响应。

1.3 路由装饰器的含义

在代码中,@app.get("/") 是 FastAPI 的核心语法。其中:

  • @app.get 表示监听 HTTP GET 请求;
  • "/" 是请求路径,对应根路径;
  • async def read_root() 是路径操作函数(Path Operation Function),负责处理请求并返回响应。

二、路径参数与动态路由设计

2.1 路径参数的定义

路径参数允许将 URL 中的动态部分提取为函数参数。例如,路径 /items/{item_id} 中的 {item_id} 即为路径参数。

示例:通过路径参数获取商品信息

@app.get("/items/{item_id}")  
async def read_item(item_id: str):  
    return {"item_id": item_id}  

当访问 http://localhost:8000/items/123 时,item_id 的值会自动绑定为 "123",并返回 JSON 数据。

2.2 路径参数的类型声明

FastAPI 通过类型注解自动解析参数类型。例如:

@app.get("/items/{item_id}")  
async def read_item(item_id: int):  
    return {"item_id": item_id}  

若传入非整数路径(如 http://localhost:8000/items/abc),FastAPI 会直接返回 422 错误,无需开发者手动处理类型校验。

2.3 路径参数的优先级

当路径中存在多个动态部分时,FastAPI 会按路径顺序匹配。例如:

@app.get("/users/{user_id}/items/{item_id}")  
async def read_user_item(user_id: int, item_id: str):  
    return {"user_id": user_id, "item_id": item_id}  

该路径会匹配类似 /users/123/items/abc 的请求。


三、查询参数与可选参数的处理

3.1 查询参数的基础用法

查询参数通过 ?key=value 的形式附加在路径后,用于传递额外信息。例如:

@app.get("/search")  
async def search(q: str | None = None):  
    return {"query": q}  

访问 http://localhost:8000/search?q=hello 时,q 的值为 "hello";若省略 q,则返回 null

3.2 可选参数与默认值

通过 = None 可将参数设为可选,并通过 | None 明确类型:

async def search(q: str | None = "default"):  
    return {"query": q or "empty"}  

此时,若不传入 q,默认值为 "default",而 or "empty" 仅用于示例逻辑,实际可省略。

3.3 多值查询参数与列表解析

若查询参数允许多次出现(如 ?tags=python&tags=fastapi),可通过 list 类型自动解析:

@app.get("/tags")  
async def read_tags(tags: list[str] = Query()):  
    return {"tags": tags}  

此时,tags 参数会直接返回一个列表 ["python", "fastapi"]


四、请求方法与路由的多样性

4.1 HTTP 方法的含义与用途

FastAPI 支持所有标准 HTTP 方法(如 GET、POST、PUT、DELETE),其核心区别在于请求的目的:
| 方法 | 用途 | 典型场景 |
|-----------|-----------------------------|----------------------|
| GET | 获取资源 | 查看用户列表 |
| POST | 创建新资源 | 提交表单或新建订单 |
| PUT | 更新资源(覆盖) | 修改用户信息 |
| DELETE | 删除资源 | 删除指定商品 |
| PATCH | 部分更新资源 | 修改用户邮箱 |

4.2 实现不同方法的路由

以下示例展示了如何为同一路径配置不同方法:

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

@app.put("/users/{user_id}")  
async def update_user(user_id: int, new_name: str):  
    return {"user_id": user_id, "new_name": new_name}  

访问 http://localhost:8000/users/1 时,GET 方法返回用户信息;而 PUT 请求可携带 new_name 参数更新数据。


五、路由的嵌套与分组:提升代码结构

5.1 使用 APIRouter 实现模块化

当 API 规模扩大时,可使用 APIRouter 将路由分组。例如:

from fastapi import APIRouter  

router = APIRouter(prefix="/v1")  

@router.get("/users")  
async def list_users():  
    return {"users": []}  

app.include_router(router)  

此时,所有 router 中的路由路径会自动添加 /v1 前缀,如 /v1/users

5.2 动态路径与嵌套路由

通过路径参数和嵌套路由,可以构建层级结构:

router = APIRouter(prefix="/products")  

@router.get("/{category}")  
async def list_category(category: str):  
    return {"category": category}  

@router.get("/{category}/{item_id}")  
async def get_item(category: str, item_id: int):  
    return {"category": category, "item_id": item_id}  

这会生成类似 /products/electronics/products/electronics/123 的路径。


六、路由中的依赖注入与安全性

6.1 依赖注入的基本概念

FastAPI 的依赖注入允许将公共逻辑(如身份验证、数据库连接)封装为可复用的函数。例如:

async def get_db():  
    return {"db": "connected"}  

@app.get("/items")  
async def read_items(db=Depends(get_db)):  
    return db  

此时,所有调用 read_items 的请求都会自动执行 get_db(),并将结果注入到 db 参数中。

6.2 结合路径参数与依赖

依赖函数可与路径参数结合使用:

async def get_user(user_id: int = Path(...)):  
    return {"user_id": user_id}  

@app.get("/users/me")  
async def get_me(current_user=Depends(get_user)):  
    return current_user  

此时,/users/me 路径需携带 user_id 路径参数,例如 /users/me/123


结论

通过本文,我们系统地学习了 FastAPI 基本路由 的核心概念与实现技巧,包括路径参数、查询参数、HTTP 方法、路由分组与依赖注入等。FastAPI 的设计哲学强调“代码即文档”,其类型注解和自动化功能极大简化了 API 开发的复杂度。无论是构建简单的 RESTful API 还是复杂的微服务系统,掌握路由设计都是开发者必须具备的基础能力。

在后续学习中,建议进一步探索 FastAPI 的响应模型、异常处理、中间件等高级特性,逐步构建出高效、健壮的 API 系统。记住,实践是掌握技术的最佳途径——尝试将本文的代码示例改写为自己的项目,并逐步添加更复杂的逻辑。

最新发布