上篇:FastAPI 核心知识梳理:路由、参数传递与文件上传完全指南

1. request 对象

概念:客户端向服务器发送的各种请求的封装。
可以通过request对象获取:请求头,各种参数如路径参数、请求体、查询参数,以及cookie等。

1.1. 获取header

request.headers.get()

示例:如何获取请求头。

from fastapi import APIRouter, Request  
request_router = APIRouter()  
  
@request_router.get("/headers/")  
async def get_request_headers(request: Request):  
	# 获取请求头  
	print(f"请求头: {request.headers}")  
	# 获取请求方法  
	print(f"请求方法: {request.method}")
    # 获取请求头中的Content-Type 
    content_type = request.headers.get("Content-Type")  
    return {  
        "content_type": content_type  
    }

运行结果:

请求头: Headers({'user-agent': 'PostmanRuntime/7.53.0', 'accept': '*/*', 'postman-token': '50813957-e7f9-4ab9-9454-1e77c7b2b2df', 'host': '127.0.0.1:8888', 'accept-encoding': 'gzip, deflate, br', 'connection': 'keep-alive'})
请求方法: GET

并返回content_type值为:null
在这里插入图片描述

1.2. 获取路径参数

request.path_params.get()

示例:如何获取路径参数

@request_router.get("/path/{name}")  
async def get_request_path_variable(request: Request):  
    print(f"请求参数: {request.path_params}")  
    # 通过path_params获取路径参数,参数名为name  
    name = request.path_params.get("name")  
    return{  
        "name": name  
    }

在路径后面补充参数zhangsan,返回"name":zhangsan
![[Pasted image 20260413201528.png]]

1.3. 获取查询参数

request.query_params.get()

示例:获取查询参数

@request_router.get("/param/")  
async def get_request_param(request: Request):  
    print(f"请求参数: {request.query_params}")  
    # 通过query_params获取查询参数,参数名为name  
    name = request.query_params.get("name")  
    return{  
        "name": name  
    }

填写param字段:key:name,value:lisi,返回参数名和参数值。
![[Pasted image 20260413201715.png]]

1.4. 获取请求体

request.json()

示例:获取请求体

@request_router.post("/body/")  
async def get_request_body(request: Request):  
    body = await request.json()  
    return{"body": body}

填写body内容,最后返回json
![[Pasted image 20260413203431.png]]

1.5. cookie

Cookie 本质上是“服务器让浏览器帮忙存数据,并在之后自动带回来”。

作用:标识用户

Cookie 的作用是“在客户端(浏览器)保存一点数据,并在后续请求中自动带上”,从而让服务器能够识别用户身份或记录状态。简单说,它解决的是 HTTP 无法记住用户的问题。

原理:服务器发 → 浏览器存 → 浏览器带 → 服务器识别

  1. 第一步,服务器在响应中通过 Set-Cookie 把一段数据发给浏览器,比如一个 session_id。
  2. 第二步,浏览器会把这个 Cookie 保存下来。
  3. 第三步,之后浏览器每次请求同一个网站时,都会自动在请求头中带上 Cookie,比如:Cookie: session_id=abc123。
  4. 第四步,服务器通过这个 session_id 就可以识别用户,比如查数据库知道你已经登录了。

特点

  1. 自动携带:浏览器会自动带上,不需要手动处理。
  2. 存储在客户端:数据保存在浏览器中。
  3. 有大小限制:一般每个 Cookie 不能太大(通常几 KB)。
  4. 可以设置生命周期:可以是会话级(关闭浏览器就没了)或长期有效。
  5. 有安全属性:比如 HttpOnly(防止被 JS 读取)、Secure(只在 HTTPS 传输)
  6. 主要用于:检验用户登录状态、保存用户偏好,以及简单的跟踪信息(比如访问记录)。

设置Cookie

服务器生成Cookie,所以需要用到Response对象。

response.set_cookie(key="xxxx",value="xxxx")

设置Cookie示例:

@request_router.post("/cookie/set")  
async def set_cookie(response : Response):  
    """  
    设置Cookie  
    :param response: 响应对象  
    :return:  
    """    # max_age 是秒数,设置Cookie的过期时间,60秒后过期  
    response.set_cookie(key="session-id", value="1234567890",max_age=60)  
    return {  
        "message": "Cookie设置成功"  
    }

获取Cookie

每次访问浏览器,都会在请求头中带上Cookie,属于请求数据,可以用request对象。

request.cookies.get()

获取Cookie示例:

@request_router.get("/cookie/get")  
async def get_cookie(request: Request):  
    """  
    获取Cookie  
    :param request: 请求对象  
    :return:  
    """    cookie = request.cookies.get("session-id")  
    return {  
        "cookie": cookie  
    }

值得一提的是,超过cookie的最大生命周期(本例中设置的是60s),便不能获取到cookie了,此时cookie为null。

1.6. 在浏览器中如何查看header或者cookie?

  1. 按住 F12 或者右键点击检查——> 点击网络——> 选择方法——> 点击Cookie。
  2. 点击标头,可以看到头信息。
    在这里插入图片描述

1.7. response-model

response_model 是 FastAPI 用来“约束和格式化返回数据”的工具。简单理解就是:你可以指定接口“最终返回的数据结构长什么样”,FastAPI 会自动帮你过滤、校验并输出。

默认情况下,你 return 什么,FastAPI 就返回什么。但在真实开发中,这样有两个问题:
第一,可能返回多余字段(比如数据库里的敏感信息);
第二,返回结构不统一,不方便前端使用。

response_model 的作用就是解决这些问题。你可以定义一个 Pydantic 模型,然后在接口中声明 response_model,这样 FastAPI 会做三件事:
1)只保留模型中定义的字段(多余的会被自动过滤)
2)自动校验返回数据类型
3)生成更清晰的接口文档(Swagger)

response-model使用实例1:

from fastapi import APIRouter  
from pydantic import BaseModel, Field  
  
  
response_router  = APIRouter()  
  
  
class UserOut(BaseModel):  
    id: int  
    name: str = Field(default="zhangsan",max_length=20,min_length=6)  
    email: str = Field(default="zhangsan@example.com", pattern=r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$')  
  
@response_router.get("/response-model",response_model=UserOut)
async def get_response():  
    return{  
        "id": 1,  
        "name": "zhangsan",  
        # 邮箱少写了 `@` 符号
        "email": "zhangsanexample.com"  
    }

在get_response()方法中,我们返回了错误的邮箱格式,此时设置的response_model 会在返回响应时校验数据,如果不符合模型定义,会报错并阻止错误数据返回给客户端。
![[Pasted image 20260413221117.png]]

response_model的其他用法:

  1. 可以传入一个对象,而输出另一个对象。比如传入一个User对象包括密码,输出的时候就可以利用response_model隐去密码字段。
  2. response 对象的属性: response_model_include(set)->({“XXX” , “XXX”})包括字段,response_model_exclude排除字段。

2. response 对象

2.1. HTMLResponse:可以在页面渲染html格式。

@response_router.get("/html_response")  
async def get_html_response():  
    return HTMLResponse('<h1>Hello HTMLResponse</h1>')

2.2. RedirectResponse:用于重定向。

@response_router.get("/redirect_response")  
async def get_redirect_response():  
    return RedirectResponse(url="https://baidu.com")

2.3. FileResponse:用于文件下载。

@response_router.get("/file_response")  
async def get_file_response():  
    path = os.path.join(os.path.dirname(__file__), "logo.png")  
    return FileResponse(path)

3. 中间件 middleware

3.1. 概念

请求到达目标API之前,将请求拦截。中间件一旦建立,项目中的所有请求都会经过该中间件。

3.2. 应用场景

  1. 认证:用户登录
  2. 鉴权:访问控制
  3. 日志管理
  4. 数据清洗:数据合法性验证
  5. 限流(流控):QPS(每秒查询数),防止QPS过高击穿网站

3.3. 实现

middleware.urls.py:

from fastapi import APIRouter  
  
middleware_router = APIRouter()  
  
@middleware_router.get("/one")  
async def action():  
    print("中间件执行中")  
    return {"message": "中间件执行中"}

main.py:

from fastapi import FastAPI, Request  
from fastapi_review.apps.middleware.urls import middleware_router   
  
app = FastAPI()  
  
# include 路由  
app.include_router(middleware_router, prefix="/middleware", tags=["中间件管理模块"])  
  
@app.middleware("http")  
async def m1(request: Request, call_next): 
	"""  
	:param request: 请求对象  
	:param call_next: 将请求继续向下传递的对象  
	:return: """ 
    print("执行中间件m1前操作")  
    response = await call_next(request)  
    print("执行中间件m1后操作")  
    return response  
  
@app.middleware("http")  
async def m2(request: Request, call_next):  
    print("执行中间件m2前操作")  
    response = await call_next(request)  
    print("执行中间件m2后操作")  
    return response

中间件从下到上执行,先执行m2再执行m1:
![[Pasted image 20260417222434.png]]

执行过程:

进入 m2
  → 进入 m1
    → 执行 API
  ← 返回 m1
← 返回 m2

输出:
在这里插入图片描述

4. 依赖系统

FastAPI的依赖系统是一种自动“管理和注入资源”的机制。FastAPI 的依赖系统允许你在路径操作函数执行前,先运行另一个函数,并把那个函数的返回值“注入”到你的路径操作函数里。

4.1. 为什么要注入依赖

假设你正在做一个管理系统,有一下接口:

  • /api/users —— 查看用户列表
  • /api/orders —— 查看订单列表
  • /api/products —— 查看商品列表
    这三个接口的共同点就是,都需要做分页查询,都需要分页参数(offset、limit)来查询数据库中的数据。

如何不使用依赖,我们的代码将会变得冗余且难以维护:

from fastapi import APIRouter
dependency_router = APIRouter() 
# 3 个接口都需要分页参数
@dependency_router.get("/users")
async def list_users(offset: int = 0, limit: int = 10):
    return query_users(offset, limit)

@dependency_router.get("/orders")
async def list_orders(offset: int = 0, limit: int = 10):
    return query_orders(offset, limit)

@dependency_router.get("/products")
async def list_products(offset: int = 0, limit: int = 10):
    return query_products(offset, limit)

痛点:

  1. 每个接口都要写一遍 offset: int = 0, limit: int = 10
  2. 如果某天要改成 limit: int = 20,要改 3 个地方
  3. 如果某天要加 max_limit=100 的限制,3 个地方都要加

4.2. 如何使用依赖

  1. 创建依赖系统(普通的函数)
  2. 在路由函数中使用Depends注入依赖
from fastapi import APIRouter, Depends, Query  
  
dependency_router = APIRouter()  
  
  
# 1.创建依赖系统(普通的函数)  
def get_page_params(offset: int = Query(0, description="分页偏移量"), limit: int = Query(10, description="分页大小")):  
    return {"offset": offset, "limit": limit}  
  
  
# 2.在路由函数中使用Depends注入依赖  
@dependency_router.get("/users/")  
async def list_users(page=Depends(get_page_params)):  
    # FastAPI 自动做了这件事:  
    # 1. 发现 get_page_params 需要 offset 和 limit    
    # 2. 从 URL 的 ?offset=xxx&limit=xxx 中取值  
    # 3. 调用 get_page_params(offset, limit)    
    # 4. 把返回值赋给 page   
    return {  
        "offset": page["offset"],  
        "limit": page["limit"]  
    }

访问:http://127.0.0.1:8888/dependency/users
offset和limit就是默认值。
在这里插入图片描述

访问http://127.0.0.1:8888/dependency/users/?offset=20&limit=5
offset和limit就是设定的值。
在这里插入图片描述

4.3. 依赖系统的三大作用

作用 没有依赖系统 有依赖系统
消除重复代码 每个接口都写一遍相同的参数定义 定义一次,处处复用
集中管理逻辑 校验规则、默认值散落在各个接口 所有逻辑集中在依赖函数中
自动解析注入 手动从 request 对象里抠参数 FastAPI 自动解析、转换、校验、注入

4.4. 常见应用场景

场景 示例
分页参数 def pagination(offset, limit): ...
用户认证 def get_current_user(token): ...
数据库连接 def get_db(): ...
权限校验 def require_admin(user): ...
请求限流 def rate_limit(): ...

4.5. 关键要点

  1. 依赖函数就是普通函数— 但参数必须用 Query()Header() 等声明来源
  2. Depends 是连接器 — 告诉 FastAPI “这个参数的值,请调用那个函数来获取”
  3. 依赖系统的本质:FastAPI 负责自动化 — 解析 HTTP 请求 → 调用依赖函数 → 注入返回值
Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐