
文章目录
-
- 1. 课前导读
-
- 本节课学习目标
- 前置知识
- 学完能掌握什么
- 适用人群
- 2. 核心理论讲解
-
- 2.1 HTTP请求方法详解与RESTful设计原则
-
- 2.1.1 主要方法对比
- 2.1.2 FastAPI中各方法的装饰器
- 2.2 HTTP状态码——与客户端沟通的语言
-
- 2.2.1 成功类(2xx)
- 2.2.2 客户端错误(4xx)
- 2.2.3 服务器错误(5xx)
- 2.2.4 FastAPI中返回状态码的方式
- 2.3 响应模型(Response Model)原理
-
- 2.3.1 基本用法
- 2.3.2 响应模型的底层逻辑
- 2.3.3 `response_model`与函数返回类型注解的关系
- 2.4 统一返回格式封装(企业级实践)
-
- 2.4.1 为什么需要统一格式?
- 2.4.2 FastAPI中如何优雅实现?
- 2.5 与Flask/Django的响应处理对比
- 3. 环境搭建 & 实操准备
-
- 3.1 复用项目环境
- 3.2 新增代码文件
- 3.3 安装依赖(无额外需求)
- 4. 手把手代码实战
-
- 4.1 不同HTTP方法的接口实现(模拟商品管理)
- 4.2 响应模型的高级用法:字段别名、排除空值、嵌套
- 4.3 自定义状态码与异常处理
- 4.4 统一返回格式封装(企业级实战)
-
- 4.4.1 定义统一响应模型
- 4.4.2 在接口中使用统一响应格式
- 4.4.3 实现全局异常拦截统一错误响应(预览)
- 4.5 使用`response_model_include`和`response_model_exclude`
- 4.6 响应模型与路径操作函数的返回类型注解配合
- 4.7 处理文件下载等非JSON响应
- 4.8 请求方法实践:创建完整CRUD + 统一响应
- 5. 重点知识点总结
-
- HTTP方法速查表
- 状态码选择最佳实践
- 响应模型核心语法
- 统一返回格式优势与实现
- 易错点与避坑指南
- 最佳实践
- 6. 课后作业 & 思考题
-
- 实操练习题(必做)
- 理论思考题
- 拓展学习方向
- 7. 本节干货总结
-
- 核心考点(面试/自测)
- 实际工作应用场景
- 下节课预告
- 🔗《20节课 FastAPI 从入门到精通》系列课程导航
1. 课前导读
本节课学习目标
在前5课中,我们已经能够创建接口并接收路径参数、查询参数和请求体数据。但一个专业的API不仅需要正确处理数据,还需要遵循HTTP规范——使用恰当的请求方法表达操作意图,返回正确的状态码告知客户端处理结果,并通过统一的响应格式提升前后端协作效率。
本节课将带你掌握FastAPI中关于HTTP协议规范落地的核心实践。学完本节课,你将:
- 理解HTTP请求方法语义:GET、POST、PUT、PATCH、DELETE等方法的正确使用场景与区别
- 掌握HTTP状态码:2xx成功、4xx客户端错误、5xx服务器错误的典型用法,以及FastAPI中如何返回特定状态码
- 学会响应模型:使用response_model参数过滤输出字段、保证类型安全、自动生成文档
- 封装统一返回格式:实现企业级API常见的{code, message, data}结构,支持泛型
- 处理异常响应:自定义异常与状态码的映射
前置知识
- 已完成第5课,熟悉Pydantic模型定义和请求体处理
- 了解基本的HTTP协议(请求方法、状态码分类)
- 知道FastAPI的路径操作装饰器(@app.get等)
学完能掌握什么
学完本节课后,你将具备以下能力:
适用人群
- 已经掌握参数接收但输出混乱的开发者
- 需要对接前端或第三方系统的后端工程师
- 希望API符合行业规范(RESTful)的学习者
- 准备进入企业级项目开发的学员
2. 核心理论讲解
2.1 HTTP请求方法详解与RESTful设计原则
HTTP协议定义了多种请求方法(也称为HTTP动词),每种方法对应一种资源操作语义。在RESTful API设计中,合理使用方法能显著提升接口的可读性和可维护性。
2.1.1 主要方法对比
| GET | 获取资源 | ✅ 是 | ✅ 是 | ❌ 否 | 查询列表、获取详情 |
| POST | 创建资源 | ❌ 否 | ❌ 否 | ✅ 是 | 注册用户、创建订单 |
| PUT | 全量更新 | ✅ 是 | ❌ 否 | ✅ 是 | 替换整个资源 |
| PATCH | 部分更新 | ❌ 否 | ❌ 否 | ✅ 是 | 修改用户部分字段 |
| DELETE | 删除资源 | ✅ 是 | ❌ 否 | ❌ 否 | 删除商品 |
关键概念解释:
- 幂等性:多次执行相同请求,产生的副作用与执行一次相同。例如:DELETE删除一个资源多次,第一次删除成功,后续返回404,但服务器状态不会再变,是幂等的。
- 安全性:不修改服务器状态(只读)。GET和HEAD是安全的。
2.1.2 FastAPI中各方法的装饰器
FastAPI为每个HTTP方法提供了对应的装饰器:
from fastapi import FastAPI
app = FastAPI()
@app.get("/resource")
def get_resource(): ...
@app.post("/resource")
def create_resource(): ...
@app.put("/resource/{id}")
def update_resource(id: int): ...
@app.patch("/resource/{id}")
def partial_update(id: int): ...
@app.delete("/resource/{id}")
def delete_resource(id: int): ...
与Flask/Django对比:
- Flask中需要显式指定methods=['GET', 'POST'],而FastAPI通过不同装饰器更清晰地表达意图。
- Django REST framework使用@action装饰器,略繁琐。
2.2 HTTP状态码——与客户端沟通的语言
状态码是服务器告诉客户端请求结果的数字代码,分为五类:
2.2.1 成功类(2xx)
| 200 OK | 成功 | GET、PUT、PATCH 成功返回数据 |
| 201 Created | 已创建 | POST 创建资源成功,通常在响应头Location中放新资源URL |
| 204 No Content | 无内容 | DELETE 成功,或 PUT 更新无需返回数据 |
| 206 Partial Content | 部分内容 | 范围请求(下载大文件断点续传) |
2.2.2 客户端错误(4xx)
| 400 Bad Request | 错误请求 | 请求体格式错误、参数校验失败(业务层面) |
| 401 Unauthorized | 未授权 | 未提供认证凭证或凭证无效 |
| 403 Forbidden | 禁止访问 | 已认证但无权限(如普通用户访问管理员接口) |
| 404 Not Found | 未找到 | 资源不存在 |
| 422 Unprocessable Entity | 无法处理 | 请求体语法正确但语义错误(Pydantic校验失败默认返回422) |
| 429 Too Many Requests | 请求过多 | 触发限流 |
2.2.3 服务器错误(5xx)
| 500 Internal Server Error | 服务器内部错误 | 未捕获的异常(框架默认) |
| 502 Bad Gateway | 网关错误 | 代理服务器收到无效响应 |
| 503 Service Unavailable | 服务不可用 | 服务器过载或维护 |
2.2.4 FastAPI中返回状态码的方式
方式1:在装饰器中指定默认状态码
@app.post("/items", status_code=201)
def create_item():
return {"id": 1}
方式2:手动返回Response对象或JSONResponse
from fastapi.responses import JSONResponse
@app.post("/items")
def create_item():
return JSONResponse(content={"id": 1}, status_code=201)
方式3:使用raise HTTPException(用于错误响应)
from fastapi import HTTPException
@app.get("/items/{id}")
def get_item(id: int):
if id not in items:
raise HTTPException(status_code=404, detail="Item not found")
return items[id]
2.3 响应模型(Response Model)原理
FastAPI允许你在路径装饰器中使用response_model参数,指定用于输出响应的Pydantic模型。这带来三大好处:
2.3.1 基本用法
from pydantic import BaseModel
class UserOut(BaseModel):
id: int
name: str
# email 字段不在此模型中,所以不会返回
@app.get("/users/{id}", response_model=UserOut)
def get_user(id: int):
# 假设从数据库查到包含 email 字段的字典
user = {"id": 1, "name": "Alice", "email": "alice@example.com"}
return user # 实际返回 {"id": 1, "name": "Alice"},email被过滤
2.3.2 响应模型的底层逻辑
当使用response_model时,FastAPI会在路径操作函数返回后,将返回值传入该模型进行序列化(model_dump()),然后输出JSON。这意味着:
- 你可以返回字典、模型实例或其他可转换对象。
- 如果返回值与模型不匹配(缺少字段或类型错误),FastAPI会抛出500错误(开发阶段应避免)。
2.3.3 response_model与函数返回类型注解的关系
推荐同时使用两者:response_model用于运行时过滤和文档,返回类型注解用于编辑器和类型检查。
@app.get("/user", response_model=UserOut)
def get_user() –> UserOut:
return user_data
2.4 统一返回格式封装(企业级实践)
在实际项目中,为了前端便于统一处理错误和成功响应,通常会封装一个统一的响应格式,例如:
{
"code": 0,
"message": "success",
"data": {…}
}
对于错误响应:
{
"code": 40001,
"message": "用户名已存在",
"data": null
}
2.4.1 为什么需要统一格式?
- 前端统一拦截:无论成功失败,都通过code字段判断,而非依赖HTTP状态码。
- 业务错误码细化:HTTP状态码有限(如400涵盖多种错误),自定义code可精确定位。
- 扩展性:可以加入timestamp、request_id等字段便于排查。
2.4.2 FastAPI中如何优雅实现?
方案:定义通用的响应模型,并编写辅助函数返回。同时利用FastAPI的response_model可以指定data字段的动态类型。
2.5 与Flask/Django的响应处理对比
| FastAPI | 装饰器参数或status_code | 可返回任意类型,自动转JSON | 内置response_model | 自定义辅助函数 |
| Flask | return jsonify(…), 201 | 需手动jsonify | 无内置,需手动过滤 | 自定义装饰器或函数 |
| Django | return JsonResponse(…, status=201) | 类似Flask | DRF提供Serializer | DRF的Response可封装 |
FastAPI的优势在于类型安全与文档自动生成的无缝集成。
3. 环境搭建 & 实操准备
3.1 复用项目环境
继续使用第5课的项目(lesson03_first_project)。确保虚拟环境已激活。
3.2 新增代码文件
在app/api/v1/下创建http_methods_demo.py,并在main.py中注册。
touch app/api/v1/http_methods_demo.py
main.py中注册:
from app.api.v1 import http_methods_demo
app.include_router(http_methods_demo.router, prefix="/api/v1/http", tags=["HTTP方法与响应"])
3.3 安装依赖(无额外需求)
4. 手把手代码实战
4.1 不同HTTP方法的接口实现(模拟商品管理)
# app/api/v1/http_methods_demo.py
from fastapi import APIRouter, HTTPException, status, Response
from pydantic import BaseModel, Field
from typing import Optional, List, Dict
from datetime import datetime
router = APIRouter()
# ———- 数据模拟 ———-
fake_products_db: Dict[int, dict] = {}
counter = 1
class ProductCreate(BaseModel):
name: str = Field(..., min_length=1)
price: float = Field(..., gt=0)
stock: int = Field(0, ge=0)
class ProductUpdate(BaseModel):
name: Optional[str] = Field(None, min_length=1)
price: Optional[float] = Field(None, gt=0)
stock: Optional[int] = Field(None, ge=0)
class ProductOut(BaseModel):
id: int
name: str
price: float
stock: int
created_at: datetime
# ———- 1. GET – 获取列表和详情 ———-
@router.get("/products", response_model=List[ProductOut])
async def list_products():
"""GET /products – 获取所有商品列表"""
return list(fake_products_db.values())
@router.get("/products/{product_id}", response_model=ProductOut)
async def get_product(product_id: int):
"""GET /products/{id} – 获取单个商品"""
product = fake_products_db.get(product_id)
if not product:
raise HTTPException(status_code=404, detail="商品不存在")
return product
# ———- 2. POST – 创建资源,返回201 ———-
@router.post("/products", response_model=ProductOut, status_code=status.HTTP_201_CREATED)
async def create_product(product: ProductCreate):
"""POST /products – 创建新商品"""
global counter
now = datetime.now()
new_product = ProductOut(
id=counter,
name=product.name,
price=product.price,
stock=product.stock,
created_at=now
)
fake_products_db[counter] = new_product.model_dump()
counter += 1
return new_product
# ———- 3. PUT – 全量更新 ———-
@router.put("/products/{product_id}", response_model=ProductOut)
async def update_product_full(product_id: int, product: ProductCreate):
"""PUT /products/{id} – 全量更新(必须提供所有字段)"""
if product_id not in fake_products_db:
raise HTTPException(status_code=404, detail="商品不存在")
existing = fake_products_db[product_id]
updated = ProductOut(
id=product_id,
name=product.name,
price=product.price,
stock=product.stock,
created_at=existing["created_at"] # 保留创建时间
)
fake_products_db[product_id] = updated.model_dump()
return updated
# ———- 4. PATCH – 部分更新 ———-
@router.patch("/products/{product_id}", response_model=ProductOut)
async def update_product_partial(product_id: int, update: ProductUpdate):
"""PATCH /products/{id} – 部分更新(只更新传递的字段)"""
if product_id not in fake_products_db:
raise HTTPException(status_code=404, detail="商品不存在")
current = fake_products_db[product_id]
# 只更新传入的非None字段
update_data = update.model_dump(exclude_unset=True)
current.update(update_data)
# 重新校验并构建ProductOut(确保类型正确)
updated = ProductOut(**current)
fake_products_db[product_id] = updated.model_dump()
return updated
# ———- 5. DELETE – 删除资源,返回204 ———-
@router.delete("/products/{product_id}", status_code=status.HTTP_204_NO_CONTENT)
async def delete_product(product_id: int):
"""DELETE /products/{id} – 删除商品,返回204 No Content"""
if product_id not in fake_products_db:
raise HTTPException(status_code=404, detail="商品不存在")
del fake_products_db[product_id]
# 返回204时不应有响应体,FastAPI会自动处理
return Response(status_code=status.HTTP_204_NO_CONTENT)
测试方法:
# 1. POST 创建商品
curl -X POST http://localhost:8000/api/v1/http/products \\
-H "Content-Type: application/json" \\
-d '{"name": "手机", "price": 2999, "stock": 100}'
# 响应201,带id和created_at
# 2. GET 列表
curl http://localhost:8000/api/v1/http/products
# 3. PUT 全量更新
curl -X PUT http://localhost:8000/api/v1/http/products/1 \\
-H "Content-Type: application/json" \\
-d '{"name": "旗舰手机", "price": 3999, "stock": 50}'
# 4. PATCH 部分更新
curl -X PATCH http://localhost:8000/api/v1/http/products/1 \\
-H "Content-Type: application/json" \\
-d '{"stock": 80}'
# 5. DELETE 删除
curl -X DELETE http://localhost:8000/api/v1/http/products/1 -v
# 响应状态码应为204
4.2 响应模型的高级用法:字段别名、排除空值、嵌套
# ———- 响应模型进阶 ———-
from pydantic import BaseModel, Field, ConfigDict
class User(BaseModel):
id: int
username: str
password: str # 敏感字段,不应返回
class UserPublic(BaseModel):
id: int
username: str
# 使用别名,输出时字段名变为 "user_name"
# 注意:Field别名会影响序列化,需要配置 model_config 或使用 serialization_alias
model_config = ConfigDict(populate_by_name=True)
@router.get("/users/{user_id}", response_model=UserPublic)
async def get_user(user_id: int):
# 模拟从数据库取出包含密码的用户数据
user = User(id=1, username="alice", password="secret")
return user # 密码不会返回,因为UserPublic中没有password字段
4.3 自定义状态码与异常处理
# ———- 自定义异常与状态码 ———-
from fastapi import HTTPException, Header
@router.post("/transfer")
async def transfer_money(
amount: float,
from_account: str,
to_account: str,
x_request_id: Optional[str] = Header(None)
):
"""
模拟转账接口,演示不同状态码的使用
"""
if amount <= 0:
raise HTTPException(status_code=400, detail="金额必须大于0")
if from_account == to_account:
raise HTTPException(status_code=400, detail="不能转入同一账户")
# 模拟余额不足(业务错误,但HTTP状态码仍用400或422)
if amount > 1000:
raise HTTPException(status_code=402, detail="余额不足") # 402 Payment Required 非标准但可用
# 成功返回200
return {"message": "转账成功", "transfer_id": "T123"}
4.4 统一返回格式封装(企业级实战)
4.4.1 定义统一响应模型
新建app/schemas/response.py(创建目录):
mkdir -p app/schemas
touch app/schemas/__init__.py
touch app/schemas/response.py
app/schemas/response.py:
from typing import Generic, TypeVar, Optional
from pydantic import BaseModel, Field
T = TypeVar('T')
class ResponseModel(BaseModel, Generic[T]):
"""
统一响应格式
code: 业务状态码,0表示成功,其他为错误码
message: 提示信息
data: 实际数据,可为None或任意类型
"""
code: int = 0
message: str = "success"
data: Optional[T] = None
@classmethod
def success(cls, data: Optional[T] = None, message: str = "success"):
return cls(code=0, message=message, data=data)
@classmethod
def error(cls, code: int = 1, message: str = "error", data: Optional[T] = None):
return cls(code=code, message=message, data=data)
4.4.2 在接口中使用统一响应格式
在http_methods_demo.py中引入并使用:
from app.schemas.response import ResponseModel
@router.get("/unified/products", response_model=ResponseModel[List[ProductOut]])
async def unified_list_products():
"""使用统一返回格式的商品列表"""
data = list(fake_products_db.values())
return ResponseModel.success(data=data)
@router.post("/unified/products", response_model=ResponseModel[ProductOut], status_code=201)
async def unified_create_product(product: ProductCreate):
"""创建商品,返回统一格式"""
# … 创建逻辑省略,假设备有new_product
# 假设 new_product 是 ProductOut 实例
return ResponseModel.success(data=new_product, message="创建成功")
@router.get("/unified/products/{product_id}", response_model=ResponseModel[ProductOut])
async def unified_get_product(product_id: int):
product = fake_products_db.get(product_id)
if not product:
return ResponseModel.error(code=404, message="商品不存在")
return ResponseModel.success(data=ProductOut(**product))
4.4.3 实现全局异常拦截统一错误响应(预览)
为了所有异常都返回统一格式,可以添加全局异常处理器(第12课详讲),这里简单展示:
from fastapi import Request
from fastapi.responses import JSONResponse
@router.exception_handler(HTTPException)
async def http_exception_handler(request: Request, exc: HTTPException):
return JSONResponse(
status_code=exc.status_code,
content=ResponseModel.error(code=exc.status_code, message=exc.detail).model_dump()
)
但通常不会覆盖FastAPI的默认422等,此部分后续课程深入。
4.5 使用response_model_include和response_model_exclude
在复杂场景中,可以动态选择返回字段:
@router.get("/products/{product_id}/partial", response_model=ProductOut, response_model_include={"id", "name"})
async def get_product_partial(product_id: int):
"""只返回id和name字段"""
product = fake_products_db.get(product_id)
if not product:
raise HTTPException(404)
return product
或者排除字段:
response_model_exclude={"created_at"}
4.6 响应模型与路径操作函数的返回类型注解配合
from typing import Annotated
@router.get("/example", response_model=ProductOut)
def example() –> ProductOut:
# 返回类型注解帮助IDE检查
return {"id": 1, "name": "test", "price": 10, "stock": 5, "created_at": datetime.now()}
如果返回的字典缺少created_at字段,Pydantic会抛出ValidationError,导致500错误。因此务必保证数据完整性。
4.7 处理文件下载等非JSON响应
统一返回格式通常仅适用于JSON API。对于文件下载、图片等,直接返回FileResponse:
from fastapi.responses import FileResponse
@router.get("/download/{file_name}")
async def download_file(file_name: str):
# 假设文件存在于 static 目录
return FileResponse(f"static/{file_name}", media_type="application/octet-stream")
4.8 请求方法实践:创建完整CRUD + 统一响应
我们将上面的商品管理接口全部改造为统一响应格式,并整合到一个完整示例中。
# 统一响应版商品管理
from app.schemas.response import ResponseModel
@router.get("/v2/products", response_model=ResponseModel[List[ProductOut]])
async def v2_list_products():
return ResponseModel.success(data=list(fake_products_db.values()))
@router.post("/v2/products", response_model=ResponseModel[ProductOut], status_code=201)
async def v2_create_product(product: ProductCreate):
global counter
now = datetime.now()
new_product = ProductOut(
id=counter,
name=product.name,
price=product.price,
stock=product.stock,
created_at=now
)
fake_products_db[counter] = new_product.model_dump()
counter += 1
return ResponseModel.success(data=new_product, message="创建成功")
@router.get("/v2/products/{product_id}", response_model=ResponseModel[ProductOut])
async def v2_get_product(product_id: int):
product = fake_products_db.get(product_id)
if not product:
return ResponseModel.error(code=404, message="商品不存在")
return ResponseModel.success(data=ProductOut(**product))
# 类似实现 PUT、PATCH、DELETE,为节省篇幅,省略部分,但思路一致
测试:
curl http://localhost:8000/api/v1/http/v2/products
# 响应: {"code":0,"message":"success","data":[…]}
5. 重点知识点总结
HTTP方法速查表
| @app.get | 查询 | 200 | ✅ |
| @app.post | 创建 | 201 | ❌ |
| @app.put | 全量更新 | 200 或 204 | ✅ |
| @app.patch | 部分更新 | 200 | ❌ |
| @app.delete | 删除 | 204 | ✅ |
状态码选择最佳实践
- 200:成功且有响应体(GET、PUT、PATCH)
- 201:创建成功,响应体应包含新资源
- 204:成功但无响应体(DELETE、PUT更新且不返回内容)
- 400:客户端请求错误(参数缺失、格式错误)
- 401:未认证
- 403:已认证但无权限
- 404:资源不存在
- 422:请求体语法正确但语义错误(Pydantic默认)
- 500:服务器内部错误(不应该显式返回,而是让框架处理)
响应模型核心语法
@app.get("/path", response_model=SomeModel, status_code=200)
def func() –> SomeModel:
return data
统一返回格式优势与实现
- 定义ResponseModel[T]泛型模型
- 提供success和error工厂方法
- 在接口中返回ResponseModel.success(data=…)
易错点与避坑指南
最佳实践
6. 课后作业 & 思考题
实操练习题(必做)
基础练习:为第5课的商品管理接口增加响应模型和统一格式
- 定义ProductOut,排除created_at敏感信息(或保留但只读)
- 所有接口使用response_model=ResponseModel[T]返回统一格式
进阶练习:实现一个用户管理接口
- 用户注册(POST):返回201,使用统一格式
- 用户信息查询(GET):返回200,但密码字段不出现在响应模型中
- 用户更新(PATCH):支持部分更新,返回200
- 用户删除(DELETE):返回204
挑战练习:实现文件上传接口(预览)
- POST /upload 接收文件,返回文件信息(文件名、大小、上传时间),使用统一格式
- 参考FastAPI File 和 UploadFile(后续课程会讲,可提前自学)
理论思考题
拓展学习方向
- RESTful API成熟度模型(Richardson Maturity Model)
- OpenAPI规范中关于响应状态码和响应模型的定义
- FastAPI的status模块:查看所有标准状态码常量
- 自定义响应类:继承JSONResponse实现统一格式自动包装
7. 本节干货总结
核心考点(面试/自测)
HTTP方法中PUT和PATCH的区别? PUT全量替换,PATCH部分更新。PUT要求幂等。
201和204状态码的区别? 201表示创建成功,通常有响应体(新资源);204表示成功但无响应体。
如何在FastAPI中返回特定的状态码? 装饰器参数status_code,或return JSONResponse(…, status_code=xxx),或raise HTTPException(status_code=xxx)。
response_model的作用是什么? 过滤输出字段、类型转换、生成文档。
统一返回格式如何设计? 通常包含code、message、data三个字段,使用泛型支持不同类型data。
实际工作应用场景
-
场景1:RESTful API设计 按照本节课的方法设计用户、订单、商品等资源接口,前端对接体验良好。
-
场景2:微服务间调用 使用统一格式封装,方便调用方解析,错误信息标准化。
-
场景3:自动生成文档 充分利用response_model,让Swagger UI展示精确的响应结构,减少沟通成本。
-
场景4:敏感数据保护 响应模型中排除密码、身份证号等字段,避免泄露。
-
场景5:版本升级兼容 通过响应模型可以增加新字段而不破坏旧客户端(只要使用extra="ignore")。
下节课预告
本节课我们规范了HTTP方法和响应输出,建立了企业级API的骨架。但到目前为止,参数校验还停留在简单的Field约束层面。实际业务中,我们需要对路径参数、查询参数、Header、Cookie等进行更复杂的校验(如正则、枚举、自定义逻辑)。
下节课(第7课),我们将深入学习:
- Query / Path / Header / Cookie参数的高级校验
- 使用Query、Path、Header、Cookie函数添加约束
- 别名、废弃参数、示例值等元数据配置
- 结合依赖注入实现参数预处理
让你的参数处理能力从“能用”提升到“专业”。
🔗《20节课 FastAPI 从入门到精通》系列课程导航
去订阅
🌟 感谢您耐心阅读到这里! 💡 如果本文对您有所启发欢迎: 👍 点赞📌 收藏 📤 分享给更多需要的伙伴。 🗣️ 期待在评论区看到您的想法, 共同进步。 🔔 关注我,持续获取更多干货内容~ 🤗 我们下篇文章见~



