FastAPI 基础入门-章节三(路径操作及路径函数)

一、FastAPI框架基础入门

1.1 什么是FastAPI

FastAPI是基于Python 3.6+类型提示构建的现代Web框架,其核心特性包括:

高性能:通过Starlette实现异步处理,性能媲美Node.js和Go智能编辑器支持:自动补全和类型检查显著提升开发效率自动生成文档:内置Swagger UI和ReDoc交互式文档数据验证:基于Pydantic库的自动数据校验标准化:兼容OpenAPI和JSON Schema规范

1.2 环境搭建与第一个API


# 创建虚拟环境(确保Python 3.6+已安装)
python -m venv venv
source venv/bin/activate  # Linux/Mac
# 或
venvScriptsactivate  # Windows

# 安装FastAPI和ASGI服务器(uvicorn是ASGI服务器,用于运行FastAPI应用)
pip install fastapi uvicorn

# main.py - 首个FastAPI应用
from fastapi import FastAPI  # 导入FastAPI类

# 创建FastAPI应用实例
app = FastAPI()

# 定义根路径的GET请求处理函数
@app.get("/")  # 使用装饰器定义路由
def read_root():
    """返回一个JSON响应,表示应用已启动"""
    return {"message": "Hello, FastAPI!"}  # 响应内容

# 仅当直接运行此脚本时启动服务器
if __name__ == "__main__":
    import uvicorn  # 导入uvicorn服务器
    # 启动应用:监听0.0.0.0:8000,启用自动重载(开发环境使用)
    uvicorn.run(app, host="0.0.0.0", port=8000)

运行与验证

在终端运行
uvicorn main:app --reload
访问
http://localhost:8000/docs
查看自动生成的交互式API文档文档会显示
GET /
接口的测试界面,点击”Try it out”可直接测试


二、API端点与路由系统

2.1 路由定义方式


from fastapi import FastAPI

app = FastAPI()

# 路径参数:{item_id} 会被视为路径变量
@app.get("/items/{item_id}")
def read_item(item_id: int):
    """
    获取指定ID的商品信息
    参数:
        item_id: 路径参数,必须是整数
    返回:
        包含商品ID的字典
    """
    return {"item_id": item_id}

# POST请求示例:创建新商品
@app.post("/items/")
def create_item(item: dict):
    """
    创建新商品
    参数:
        item: 请求体中的JSON数据(字典)
    返回:
        包含"created"键的字典
    """
    return {"created": item}

关键点说明


@app.get()
/
@app.post()
装饰器定义HTTP方法
{item_id}
是路径参数,FastAPI会自动将其转换为
item_id
变量参数类型注解(如
item_id: int
)触发数据验证无需手动解析请求数据,FastAPI自动处理

2.2 路由组织最佳实践


from fastapi import APIRouter, FastAPI

# 创建路由组
router = APIRouter(
    prefix="/users",  # 路由前缀
    tags=["User APIs"]  # 文档标签
)

# 用户列表路由
@router.get("/")
def list_users():
    """返回用户列表"""
    return ["user1", "user2"]

# 获取单个用户路由
@router.get("/{user_id}")
def get_user(user_id: int):
    """获取指定ID的用户信息"""
    return {"user_id": user_id}

# 主应用实例
app = FastAPI()

# 将路由组包含到主应用
app.include_router(router)

优势解析


APIRouter
实现路由模块化,便于大型项目维护
prefix
自动添加到所有子路由路径(如
/users/

tags
用于在文档中组织API分组保持主应用文件简洁,业务逻辑分散到不同模块


三、参数处理详解

3.1 路径参数(Path Parameters)


from fastapi import Path  # 导入Path类型

@app.get("/items/{item_id}")
def read_item(
    item_id: int = Path(...,  # ... 表示必填参数
                        title="Item ID",  # 文档标题
                        description="ID of the item to get",  # 描述
                        ge=1,  # 最小值(greater than or equal to 1)
                        le=100),  # 最大值(less than or equal to 100)
    q: str = Path(None, max_length=50)  # 可选参数,最大长度50
):
    """
    获取商品详情,带路径参数验证
    参数:
        item_id: 必填整数,1-100范围
        q: 可选字符串,最大长度50
    返回:
        包含商品ID和查询参数的字典
    """
    return {"item_id": item_id, "q": q}

验证规则说明


ge=1
:要求参数值 ≥ 1(最小值)
le=100
:要求参数值 ≤ 100(最大值)
max_length=50
:限制字符串最大长度
None
表示可选参数(默认值为None)
...
表示必填参数(无默认值)

测试示例

有效请求:
/items/5?q=search
→ 返回
{"item_id":5, "q":"search"}
无效请求:
/items/0?q=test
→ 返回422错误(参数验证失败)

3.2 查询参数(Query Parameters)


from fastapi import Query  # 导入Query类型

@app.get("/search")
def search_items(
    q: str = Query(...,  # 必填参数
                   min_length=3,  # 最小长度3
                   max_length=50,  # 最大长度50
                   description="Search term"),  # 参数描述
    skip: int = Query(0, ge=0),  # 默认值0,最小值0
    limit: int = Query(10, le=100)  # 默认值10,最大值100
):
    """
    搜索功能,支持分页和查询词
    参数:
        q: 必填字符串,长度3-50
        skip: 可选整数,分页偏移量(默认0)
        limit: 可选整数,分页大小(默认10,最大100)
    返回:
        包含搜索参数的字典
    """
    return {"q": q, "skip": skip, "limit": limit}

关键特性


Query(...)
:标记必填参数
min_length
/
max_length
:字符串长度限制
ge
/
le
:数值范围限制默认值:
skip=0
表示参数可选,有默认值文档自动生成:在Swagger UI中会显示参数描述和限制

请求示例


GET /search?q=fastapi&skip=10&limit=20

返回:
{"q": "fastapi", "skip": 10, "limit": 20}

3.3 请求体(Body Parameters)


from pydantic import BaseModel  # 导入Pydantic模型
from fastapi import Body  # 导入Body类型

# 定义请求体模型
class Item(BaseModel):
    name: str  # 必填字符串
    price: float  # 必填浮点数
    is_offer: bool = None  # 可选布尔值(默认None)

@app.put("/items/{item_id}")
def update_item(
    item_id: int,
    item: Item = Body(...,  # 必填请求体
                      embed=True)  # 嵌套结构处理
):
    """
    更新商品信息
    参数:
        item_id: 路径参数
        item: 请求体(JSON格式),需符合Item模型
    返回:
        包含商品ID和更新内容的字典
    """
    return {"item_id": item_id, "item": item}

嵌套结构说明


embed=True
:当请求体是JSON对象时,FastAPI会将其嵌套在顶层
无embed:
{"name": "Foo", "price": 42}
有embed:
{"item": {"name": "Foo", "price": 42}}

Pydantic自动验证请求体:
字段类型检查(name必须是字符串)必填字段验证(price必须提供)自动返回422错误(验证失败)

请求示例(使用curl):


curl -X PUT "http://localhost:8000/items/42" 
  -H "Content-Type: application/json" 
  -d '{"name": "Foo", "price": 42}'

3.4 表单数据与文件处理


from fastapi import File, UploadFile, Form  # 导入文件处理类型

@app.post("/upload")
def upload_file(
    file: UploadFile = File(...),  # 必填文件
    description: str = Form(...)  # 必填表单字段
):
    """
    处理文件上传和表单数据
    参数:
        file: 上传的文件(必填)
        description: 表单描述(必填)
    返回:
        包含文件信息的字典
    """
    return {
        "filename": file.filename,  # 文件原始名称
        "description": description,  # 表单描述
        "content_type": file.content_type  # 文件MIME类型
    }

关键点解析


File(...)
:指定为文件上传字段(必填)
Form(...)
:获取表单字段(必填)
UploadFile
对象包含:

filename
:客户端原始文件名
content_type
:MIME类型(如
image/jpeg

file
:文件对象(可读取内容)
请求格式:必须使用
multipart/form-data
(浏览器表单提交)

curl测试示例


curl -X POST "http://localhost:8000/upload" 
  -F "file=@/path/to/file.txt" 
  -F "description=Sample file"

四、Header与Cookie参数处理

4.1 请求头(Header)参数


from fastapi import Header  # 导入Header类型

@app.get("/headers")
def get_headers(
    user_agent: str = Header(...,  # 必填请求头
                            convert_underscores=False),  # 保持下划线原样
    x_token: list[str] = Header(None)  # 可选列表(支持重复头)
):
    """
    获取请求头信息
    参数:
        user_agent: 必填请求头(保持下划线原样)
        x_token: 可选请求头(支持多个值)
    返回:
        包含请求头信息的字典
    """
    return {
        "user_agent": user_agent,  # User-Agent值
        "x_token": x_token  # X-Token值(列表形式)
    }

特殊参数说明


convert_underscores=False
:默认情况下FastAPI会将
user_agent
转换为
User-Agent
,此参数保持原样
list[str]
:允许接收多个相同名称的头(如
X-Token: a

X-Token: b
)标准请求头(如
User-Agent
)会自动包含在请求中

请求示例


GET /headers HTTP/1.1
User-Agent: FastAPI-Client
X-Token: token1
X-Token: token2

4.2 Cookie参数管理


from fastapi import Cookie, Depends  # 导入Cookie和依赖注入

@app.get("/cookies")
def get_cookies(
    ads_id: str = Cookie(None),  # 可选Cookie
    session_id: str = Cookie(...)  # 必填Cookie
):
    """
    获取Cookie值
    参数:
        ads_id: 可选Cookie(默认None)
        session_id: 必填Cookie
    返回:
        包含Cookie值的字典
    """
    return {"ads_id": ads_id, "session_id": session_id}

# 使用Pydantic模型管理多个Cookie
from pydantic import BaseModel

class UserCookies(BaseModel):
    session_id: str  # 必填
    tracking_id: str = None  # 可选

@app.get("/user-cookies")
def get_user_cookies(cookies: UserCookies = Depends()):
    """
    通过依赖注入获取Cookie
    参数:
        cookies: UserCookies模型(自动从Cookie解析)
    返回:
        解析后的Cookie对象
    """
    return cookies

Cookie处理解析


Cookie(...)
:标记为必填Cookie
Cookie(None)
:标记为可选Cookie(默认None)
Depends()
:依赖注入机制,自动从Cookie解析Pydantic模型验证Cookie结构:

session_id
必须存在
tracking_id
可选

设置Cookie示例(在响应中):


from fastapi import Response

@app.post("/login")
def login(response: Response):
    response.set_cookie(key="session_id", value="abc123")
    return {"message": "Login successful"}

五、完整示例解析

5.1 综合API实现


from fastapi import FastAPI, Path, Query, Body, File, UploadFile, Header, Cookie, Depends
from pydantic import BaseModel
from typing import Optional, List

app = FastAPI()

# 定义商品模型
class Item(BaseModel):
    name: str
    description: Optional[str] = None  # 可选字段
    price: float
    tax: Optional[float] = None  # 可选字段

@app.post("/items/{item_id}", status_code=201)
def create_item(
    item_id: int = Path(...,  # 必填路径参数
                        title="Item ID",
                        ge=1, 
                        description="ID of the item to create"),
    item: Item = Body(...,  # 必填请求体
                      embed=True),
    user_agent: str = Header(default=None),  # 请求头(可选)
    x_token: List[str] = Header(default=None),  # 多值请求头
    file: UploadFile = File(...),  # 必填文件
    session_id: str = Cookie(...)  # 必填Cookie
):
    """
    创建新商品的综合API
    参数:
        item_id: 商品ID(1-100)
        item: 商品数据(JSON请求体)
        user_agent: User-Agent请求头
        x_token: X-Token请求头(支持多个值)
        file: 上传的文件
        session_id: 会话Cookie
    返回:
        包含所有参数的响应
    """
    return {
        "item_id": item_id,
        "item": item,
        "user_agent": user_agent,
        "x_token": x_token,
        "filename": file.filename,
        "session_id": session_id
    }

5.2 测试用例(详细说明)


# 使用curl测试完整API
curl -X POST "http://localhost:8000/items/42" 
  -H "Content-Type: application/json" 
  -H "Authorization: Bearer my_token" 
  -H "X-Token: first" 
  -H "X-Token: second" 
  -H "User-Agent: FastAPI-Test" 
  -F 'file=@/path/to/test.txt' 
  -F 'item={"name": "FastAPI", "price": 42.0}' 
  -b "session_id=abc123"

参数解析

参数 类型 说明 示例值

item_id
路径参数 商品ID
42

item
请求体 商品数据
{"name": "FastAPI", "price": 42.0}

Authorization
Header 认证头
Bearer my_token

X-Token
Header 多值头
first

second

User-Agent
Header 浏览器标识
FastAPI-Test

file
文件 上传文件
test.txt

session_id
Cookie 会话ID
abc123

响应示例


{
  "item_id": 42,
  "item": {
    "name": "FastAPI",
    "description": null,
    "price": 42.0,
    "tax": null
  },
  "user_agent": "FastAPI-Test",
  "x_token": [
    "first",
    "second"
  ],
  "filename": "test.txt",
  "session_id": "abc123"
}

六、最佳实践总结

6.1 参数验证原则

必填参数:使用
= ...
(不提供默认值)范围限制
ge
/
le
(数值),
min_length
/
max_length
(字符串)类型安全:通过类型注解自动验证文档友好:添加
title
/
description
提升文档可读性

6.2 路由组织规范

使用
APIRouter
分割功能模块为每个路由组添加
prefix

tags
保持单一职责:每个路由处理一个明确功能

6.3 文件与表单处理

优先使用
File

Form
类型避免手动处理
multipart
数据限制文件大小(通过
max_files

max_size
参数)

6.4 安全建议

路径参数:始终使用
ge
/
le
避免无效ID查询参数:限制长度和范围防止注入Cookie:使用
secure

http_only
标志(在生产环境)敏感数据:避免在URL中传递敏感信息(使用请求体或Cookie)


七、性能优化建议

7.1 异步处理


from fastapi import FastAPI
import httpx  # 异步HTTP客户端

app = FastAPI()

@app.get("/async")
async def async_endpoint():
    """异步示例:使用async/await处理IO操作"""
    async with httpx.AsyncClient() as client:  # 异步客户端
        response = await client.get("https://example.com")  # 等待网络请求
    return {"content": response.text}  # 返回响应内容

优势

非阻塞I/O操作(网络/数据库)提升并发处理能力适用于高延迟操作

7.2 缓存策略


from fastapi_cache import FastAPICache
from fastapi_cache.backends.redis import RedisBackend
import redis

app = FastAPI()

# 启动时初始化缓存
@app.on_event("startup")
async def startup():
    redis_client = redis.Redis(host="localhost", port=6379, db=0)
    FastAPICache.init(RedisBackend(redis_client), prefix="fastapi-cache")

@app.get("/cached")
def cached_endpoint():
    """带缓存的API,缓存5分钟"""
    return {"message": "This response is cached"}

配置说明

使用Redis作为缓存后端
prefix
用于区分不同应用的缓存默认缓存时间:5分钟(可配置)自动处理缓存命中/未命中


结论

FastAPI通过类型提示自动验证,将API开发提升到新高度。本教程详细解析了:

路径参数:使用
Path
实现路径变量验证查询参数:通过
Query
添加长度/范围限制请求体:结合Pydantic模型实现结构化数据验证表单与文件
File

Form
简化文件上传处理Header/Cookie:安全获取请求元数据

关键优势总结

开发效率:类型提示+自动文档✅ 数据安全:自动验证避免脏数据✅ 性能:异步支持+缓存集成✅ 可维护性:模块化路由+清晰参数定义

通过掌握这些核心参数处理技术,您已具备构建健壮、安全、高性能API的基础能力。在实际项目中,建议:

为所有参数添加描述(
description
)为必填参数使用
...
(不提供默认值)为数值参数添加范围限制(
ge
/
le
)使用
APIRouter
组织大型应用

最后提醒:FastAPI的文档是最佳学习资源,始终通过访问
/docs
验证您的API设计。随着您对参数处理的深入,将能构建出既符合REST规范又高度安全的生产级API。

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
TaylorSwiftie_Lover的头像 - 鹿快
评论 抢沙发

请登录后发表评论

    暂无评论内容