第三章 FastAPI 核心概念(快速上手)
本章目标:掌握 FastAPI 的路由、参数、请求体、响应等核心概念,能够定义各种接口。
3.1 路由:URL 和函数的对应关系
“路由”就是:当用户访问某个 URL 时,程序应该执行哪个函数。
最简单的路由
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def index():
return {"message": "首页"}
@app.get("/about")
def about():
return {"message": "关于我们"}
| 访问的URL | 执行的函数 | 返回结果 |
|---|---|---|
GET / | index() | {"message": "首页"} |
GET /about | about() | {"message": "关于我们"} |
@app.get("/about") 这行叫装饰器,它告诉 FastAPI:“当有人用 GET 方法访问 /about 时,就运行下面这个函数。”
不同的 HTTP 方法对应不同的装饰器
@app.get("/todos") # 查询
@app.post("/todos") # 新增
@app.put("/todos/1") # 修改
@app.delete("/todos/1") # 删除
3.2 路径参数
有时候 URL 中的一部分是动态的。比如查询第 1 个用户和第 2 个用户,URL 不同:
GET /users/1
GET /users/2
这个动态的部分就是路径参数:
@app.get("/users/{user_id}")
def get_user(user_id: int):
return {"user_id": user_id, "name": f"用户{user_id}"}
关键点:
- URL 中用
{user_id}表示这是一个变量 - 函数参数
user_id: int接收这个变量,并且自动转换为整数 - 如果传的不是数字(比如
/users/abc),FastAPI 会自动返回 422 错误
试试访问:
http://127.0.0.1:8000/users/1→{"user_id": 1, "name": "用户1"}http://127.0.0.1:8000/users/42→{"user_id": 42, "name": "用户42"}
3.3 查询参数
查询参数就是 URL 中 ? 后面的部分:
GET /users?name=张三&age=20
在 FastAPI 中,函数参数中不在路径里的参数会自动被识别为查询参数:
@app.get("/search")
def search(keyword: str, page: int = 1):
return {
"keyword": keyword,
"page": page,
"message": f"正在搜索:{keyword},第{page}页"
}
关键点:
keyword: str→ 必传参数(不传会报错)page: int = 1→ 可选参数(不传默认为1)
试试访问:
/search?keyword=Python→{"keyword": "Python", "page": 1, ...}/search?keyword=Python&page=3→{"keyword": "Python", "page": 3, ...}/search→ 报错 422(因为 keyword 是必传的)
3.4 请求体(接收 JSON 数据)
当前端要发送一整块数据给后端时(比如提交一个表单),使用请求体。
请求体通常用在 POST 和 PUT 请求中。
用 Pydantic 模型定义请求体
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class TodoCreate(BaseModel):
title: str
done: bool = False
@app.post("/todos")
def create_todo(todo: TodoCreate):
return {
"message": "创建成功",
"data": {
"title": todo.title,
"done": todo.done
}
}
代码解释:
- 定义一个类
TodoCreate,继承BaseModel - 类里面写字段名和类型(跟 Python 类型注解一样)
done: bool = False表示这个字段可选,默认为 False- 在接口函数中,参数
todo: TodoCreate告诉 FastAPI:请求体应该长这样
前端发送的 JSON:
{
"title": "买牛奶",
"done": false
}
FastAPI 会自动:
- 检查 JSON 格式是否正确
- 检查字段类型是否匹配
- 如果不对,返回 422 错误并告诉你哪里有问题
这就是 FastAPI 的强大之处:自动数据校验,省去大量手写校验代码。
3.5 响应数据
FastAPI 中返回数据非常简单:
返回字典(自动转 JSON)
@app.get("/hello")
def hello():
return {"message": "你好"}
返回列表
@app.get("/items")
def get_items():
return [
{"id": 1, "name": "苹果"},
{"id": 2, "name": "香蕉"},
]
HTTP 状态码
每个响应都有一个状态码,表示这次请求的结果:
| 状态码 | 含义 | 什么时候出现 |
|---|---|---|
| 200 | OK,成功 | 正常返回数据 |
| 201 | Created,创建成功 | 新增数据成功 |
| 404 | Not Found,找不到 | 请求的资源不存在 |
| 422 | 参数校验失败 | 请求参数格式不对 |
| 500 | 服务器错误 | 后端代码出 bug 了 |
在 FastAPI 中可以指定接口的状态码:
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.post("/todos", status_code=201)
def create_todo(todo: TodoCreate):
return {"message": "创建成功"}
@app.get("/todos/{todo_id}")
def get_todo(todo_id: int):
# 假设没找到
raise HTTPException(status_code=404, detail="待办事项不存在")
HTTPException 可以主动抛出一个错误响应,前端会收到对应的状态码和错误信息。
3.6 用 /docs 页面测试接口
还记得上一章提到的 http://127.0.0.1:8000/docs 吗?
现在我们有了多个接口,打开 /docs 页面,你会看到所有接口都列在上面。
怎么用 /docs 测试
- 点击某个接口(比如
POST /todos) - 点击右上角的 “Try it out” 按钮
- 在请求体中填写 JSON 数据
- 点击 “Execute” 按钮
- 下方会显示响应结果(状态码 + 返回的 JSON)
这样你不需要写前端页面,就能测试后端的每个接口是否正常工作。
3.7 动手练习
把以下代码保存为 main.py,启动服务后在 /docs 页面逐个测试:
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
app = FastAPI()
# ---------- 请求体模型 ----------
class TodoCreate(BaseModel):
title: str
done: bool = False
# ---------- 模拟数据库(用列表临时存储) ----------
fake_db: list[dict] = []
next_id = 1
# ---------- 接口 ----------
@app.get("/")
def index():
return {"message": "Todo 后台服务已启动"}
@app.get("/todos")
def get_todos():
return fake_db
@app.post("/todos", status_code=201)
def create_todo(todo: TodoCreate):
global next_id
new_todo = {"id": next_id, "title": todo.title, "done": todo.done}
fake_db.append(new_todo)
next_id += 1
return new_todo
@app.get("/todos/{todo_id}")
def get_todo(todo_id: int):
for todo in fake_db:
if todo["id"] == todo_id:
return todo
raise HTTPException(status_code=404, detail="待办事项不存在")
启动后试试:
- 访问
GET /todos→ 应该返回空列表[] - 用
POST /todos创建几条数据 - 再次
GET /todos→ 应该能看到刚才创建的数据 - 用
GET /todos/1查看单条数据 - 用
GET /todos/999→ 应该返回 404 错误
注意:现在数据存在列表(内存)里,服务一重启数据就没了。下一章我们就来解决这个问题——用数据库持久化存储。
本章小结
| 概念 | 说明 |
|---|---|
| 路由 | URL 和函数的对应关系,用装饰器定义 |
| 路径参数 | URL 中的动态部分,如 /users/{id} |
| 查询参数 | URL 中 ? 后面的键值对 |
| 请求体 | POST/PUT 时发送的 JSON 数据,用 Pydantic 模型定义 |
| 响应 | 直接 return 字典或列表,自动转 JSON |
| 状态码 | 200 成功 / 404 找不到 / 422 参数错误 / 500 服务器错误 |
| /docs | FastAPI 自动生成的接口文档,可以直接测试接口 |
下一章,我们学习数据库,让数据能够真正保存下来。