首页 / 知识库 / 0基础入门-阅读资料 / 0基础-后台入门

第三章 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 /aboutabout(){"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
        }
    }

代码解释:

  1. 定义一个类 TodoCreate,继承 BaseModel
  2. 类里面写字段名和类型(跟 Python 类型注解一样)
  3. done: bool = False 表示这个字段可选,默认为 False
  4. 在接口函数中,参数 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 状态码

每个响应都有一个状态码,表示这次请求的结果:

状态码含义什么时候出现
200OK,成功正常返回数据
201Created,创建成功新增数据成功
404Not 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 测试

  1. 点击某个接口(比如 POST /todos
  2. 点击右上角的 “Try it out” 按钮
  3. 在请求体中填写 JSON 数据
  4. 点击 “Execute” 按钮
  5. 下方会显示响应结果(状态码 + 返回的 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="待办事项不存在")

启动后试试:

  1. 访问 GET /todos → 应该返回空列表 []
  2. POST /todos 创建几条数据
  3. 再次 GET /todos → 应该能看到刚才创建的数据
  4. GET /todos/1 查看单条数据
  5. GET /todos/999 → 应该返回 404 错误

注意:现在数据存在列表(内存)里,服务一重启数据就没了。下一章我们就来解决这个问题——用数据库持久化存储。


本章小结

概念说明
路由URL 和函数的对应关系,用装饰器定义
路径参数URL 中的动态部分,如 /users/{id}
查询参数URL 中 ? 后面的键值对
请求体POST/PUT 时发送的 JSON 数据,用 Pydantic 模型定义
响应直接 return 字典或列表,自动转 JSON
状态码200 成功 / 404 找不到 / 422 参数错误 / 500 服务器错误
/docsFastAPI 自动生成的接口文档,可以直接测试接口

下一章,我们学习数据库,让数据能够真正保存下来。