[toc]
FastAPI笔记1

FastAPI 介绍
FastAPI 是一个用于构建 API 的现代、快速(高性能)的 web 框架,专为在 Python 中构建 RESTful API 而设计。
FastAPI 特点
- 高性能: FastAPI是建立在Starlette和Pydantic之上的,利用异步(asynchronous)编程,提供出色的性能。
- 自动文档生成: 自动生成交互式API文档,支持Swagger UI和ReDoc,让API的理解和测试更加直观。
- 类型注解支持: 利用Python的类型提示,提供更严格的输入验证和更好的代码提示。
- 异步支持: 支持异步请求处理,使得处理IO密集型任务更加高效。
FastAPI 使用场景
- 构建API后端: 用于构建RESTful API,支持前后端分离的Web应用。
- 微服务架构: 可以作为微服务的后端框架,支持快速开发和部署。
- 数据处理API: 适用于处理数据,接收和返回JSON数据。
- 实时通信: 支持WebSocket,适用于实时通信场景。
什么是 Starlette 和 Pydantic ?
FastAPI是建立在Starlette和Pydantic之上的。那么Starlette和Pydantic是什么?
Starlette 是一个轻量级的异步Web库,用于构建高性能、可扩展和易维护的Web应用程序。
- Starlette是基于Python的asyncio库构建的,因此完全支持异步编程。
- Starlette的设计目标之一是保持简单和轻量级。
- Starlette提供了灵活的路由系统,可以根据URL模式将请求路由到相应的处理函数。
- Starlette内置了异常处理机制,可以捕获和处理应用程序中的异常。 ....
Pydantic 是一个用于数据验证和解析的库。它的主要目标是使数据验证变得简单且易于维护。
- Pydantic 使用Python的类型注解来定义数据模型,使得代码更具可读性和可维护性。
- Pydantic 自动验证输入数据是否符合定义的模型规范。
- Pydantic 能够将原始数据解析成Python对象。
- Pydantic 可以根据数据模型自动生成文档,包括字段名称、数据类型、默认值等信息。
Starlette和Pydantic和FastAPI的关联。

- Starlette是负责FastAPI中的web部分(异步web服务等)。
- Pydantic是负责FastAPI中的数据模型部分(类型提示等)。
FastAPI 安装
FastAPI 依赖 Python 3.8 及更高版本。
# 使用 pip 命令来安装FastAPI
pip install fastapi另外通过FastAPI构建的web应用程序需要运行在web服务器上。因此我们还需要安装一个 ASGI 服务器,在生产环境上可以使用 Uvicorn。
Uvicorn是一个基于ASGI的高性能Web服务器,专门用于运行ASGI应用程序,即FastAPI构造的应用程序。
# 使用 pip 命令来安装uvicorn
pip install "uvicorn[standard]"第一个 FastAPI 应用
① 创建一个 main.py 的文件,并进行编辑。
# 导入fastapi包的FastAPI类
from fastapi import FastAPI
# 创建 FastAPI 应用实例 app。用于定义和管理应用的各个组件
app = FastAPI()
# 在app应用实例上添加一个根路径 / 的路由。get请求的
@app.get("/")
def read_root():
return {"Hello": "World"}
# 在app应用实例上添加一个路径为 /test 的异步路由。post请求的
@app.post("/test")
async def test():
return {"test": "test"}代码解析:
@app.get("xxx")这是一个装饰器。表示当请求路径匹配上路由的路径时,将执行这个装饰器装饰的函数。函数返回值就是请求的响应数据。async def test():意思是该函数是一个异步函数。没有表示是一个同步函数。
② 在main.py文件的当前目录下,命令行中运行以下命令以启动FastAPI应用程序。
# uvicorn 启动命令语法
uvicorn 文件名称:app --reload
# --reload 当文件修改后,会自动重写加载。
# main是要执行的py文件的名称
uvicorn main:app --reload
默认情况下uvicorn服务器的启动端口为8000
③ 浏览器访问各个请求路径。

API文档
FastAPI 提供了内置的交互式 API 文档,使开发者能够轻松了解和测试 API 的各个接口。
这个文档是自动生成的,基于 OpenAPI 规范,支持 Swagger UI 和 ReDoc 两种交互式界面。
- 你可以通过访问
http://127.0.0.1:8000/docs来打开 Swagger UI 风格的文档。 - 你也可以通过访问
http://127.0.0.1:8000/redoc来打开 ReDoc 风格的文档。
Swagger UI 风格的文档 
ReDoc 风格的文档 
FastAPI应用的启动端口和启动IP
默认情况下uvicorn服务器的启动端口为8000,启动IP为127.0.0.1
下面代码可以进行更改
# --reload 当文件修改后,会自动重写加载。
# main是要执行的py文件的名称
# --host 启动ip
# --port 启动端口
uvicorn main:app --host 0.0.0.0 --port 38080 --reload路径操作装饰器
@something语法在 Python 中被称为「装饰器」。
而在 FastAPI 中,每个路由都通过路径操作装饰器来映射到程序中的一个函数中。
简而言之,路径操作装饰器用来绑定路由和函数。
常见的路径操作装饰器如下
from fastapi import FastAPI
app = FastAPI()
## 四种HTTP请求方式的装饰器
@app.get()
@app.post()
@app.put()
@app.delete()
## 请求参数相关的装饰器
@app.options()
@app.head()
@app.patch()
@app.trace()路径操作装饰器的参数
我们可以给路径操作装饰器中传入许多参数。从而实现不同的效果。
常用的装饰器参数如下。更多的参数请查询文档。
from fastapi import FastAPI
app = FastAPI()
# 此处以post请求的路径操作装饰器举例
@app.post(
path,
response_model,
status_code,
tags,
summary="xxx",
description="xxx",
response_description="xxx",
responses,
deprecated=False
....
)tags,summary,description等参数
tags,summary,description等参数主要用于给文档中的接口添加详细信息。
例子
@app.post("/test",tags=["这是test接口的tag"],
summary="这是test接口的summary",
description="这是test接口的description",
response_description="这是test接口的response_description")
def test():
return {"Hello": "World"}文档中的效果如下图所示。 
FastAPI 路由
APIRouter函数
在上面的第一个 FastAPI 应用的代码中。我们是先通过FastAPI()函数创建出FastAPI应用实例,然后直接在FastAPI应用实例上添加路由。如下面代码所示。
# 导入fastapi包的FastAPI类
from fastapi import FastAPI
# 创建 FastAPI 应用实例 app。用于定义和管理应用的各个组件
app = FastAPI()
# 在app应用实例上添加一个根路径 / 的路由
@app.get("/")
def read_root():
return {"Hello": "World"}但是这种方式不规范,这种方式是直接把FastAPI应用实例和路由进行绑定,从而导致无法区分不同种类路由。因此FastAPI提供了一个APIRouter函数,专门用于路由管理。
如下面代码所示
# 导入fastapi包的FastAPI类
from fastapi import FastAPI,APIRouter
# 创建 FastAPI 应用实例。用于定义和管理应用的各个组件
app = FastAPI()
# 创建路由实例
router = APIRouter()
# 创建根路由
@router.get("/")
def test():
return {"Hello": "World"}
# 创建/test路由
@router.get("/test")
def test():
return {"test": "test"}
# 通过include_router函数,把应用实例app与路由实例router绑定
app.include_router(router)router = APIRouter()APIRouter函数用来创建路由实例。之后再路由实例上添加具体的路由。app.include_router(router)通过include_router函数,把应用实例app与路由实例router绑定在一起。
通过这种方式,我们可以把FastAPI的应用实例和路由实例分离开来。从而降低代码之间的耦合度。
include_router函数
如上面代码所示,include_router函数可以将应用实例与路由实例绑定。除此之外,include_router函数还可以给不同分类的路由添加前缀,标签,注释等信息。
from fastapi import FastAPI,APIRouter
app = FastAPI()
router = APIRouter()
@router.get("/test")
def test():
return {"Hello": "World"}
app.include_router(router,prefix="/module01",tags=["这是模块01的接口"])
多个模块的路由管理
在正式项目中,一个FastAPI应用通常由多个模块(多个包)组件的。每个模块都拥有自己的路由。
假设一个FastAPI应用的工程目录结构如下所示。
├── fastapi-app
│ ├── __init__.py
│ ├── main.py
│ └── module01
│ │ ├── __init__.py
│ │ └── module01Routers.py
│ └── module02
│ │ ├── __init__.py
│ │ └── module02Routers.py模块01的module01Routers.py文件代码如下
from fastapi import APIRouter
router = APIRouter()
# 用户模块的测试接口
@router.get("/user/test")
async def usertest():
return {"test": "test"}模块02的module02Routers.py文件代码如下
from fastapi import APIRouter
router = APIRouter()
# 订单模块的测试接口
@router.get("/order/test")
async def ordertest():
return {"test": "test"}main.py文件代码如下
# 导入FastAPI
from fastapi import FastAPI
# 创建FastAPI应用实例
app = FastAPI()
# 导入各个模块
from module01 import module01Routers
from module02 import module02Routers
# 通过include_router函数,把各个模块的路由实例加入到FastAPI应用实例中
app.include_router(module01Routers.router,prefix="/module01",tags=["这是模块01的接口"])
app.include_router(module02Routers.router,prefix="/module02",tags=["这是模块02的接口"])通过上面的方式,各个模块的路由分开编写,并且通过include_router函数整合到FastAPI应用实例中。

FastAPI 请求
FastAPI 提供了多种方式来获取不同类型的请求参数,并根据需要生成规范的响应。
查询参数
通常情况下查询参数是指请求路径URL中?后面拼接的键值对字符串。格式为key=value&key2=value2。
假设请求路径URL如:http://127.0.0.1:8000/test?a=1&b=2。那么请求中?后面的a=1&b=2键值对就是查询参数a和b。
默认情况下路由函数形参需要与查询参数同名。这样形参才能接收到查询参数的数据。
from fastapi import APIRouter
router = APIRouter()
@router.get("/test")
def test(a,b):
return {"a": a, "b": b}
# 给函数参数设置默认值
@router.get("/test2")
# a: int = 0 把参数a的类型设置为整数类型。默认值为 0。
def test2(a: int = 0, b: int = 10):
return {"a": a, "b": b}
# 将函数参数设置为可选参数
@router.get("/test3")
def test3(a: int = 0, b: int = None):
return {"a": a, "b": b}
路径参数
路径参数是直接包含在请求 URL 路径中的参数。路径参数是以占位符的形式出现的,格式为 http://127.0.0.1:8000/items/{item_id}。
当函数中的形参与路径参数同名的时候,函数形参才能接受到路径参数的数据。
from fastapi import APIRouter
router = APIRouter()
# /items/{item_id} 定义了一个请求路径,其中{item_id} 是路径参数,对应于函数参数 item_id。
@router.get("/items/{item_id}")
# 函数参数item_id,数据类型为int
def read_item(item_id: int):
return {"item_id": item_id}
请求头参数
有些情况下,我们想要可以获取请求头中的各个数据。例如请求头 header,请求url,cookis等。
以下有两种方式可以获取请求头参数
方式1:使用 Header 类
from fastapi import APIRouter
from fastapi import Header
router = APIRouter()
@router.get("/get_header")
# 直接在函数中定义参数。参数名需要与请求头中的键名相同。
def get_header(user_agent: str = Header(None), x_custom_header: str = Header(None)):
return {"User-Agent": user_agent, "X-Custom-Header": x_custom_header}方式2:使用Request对象来获取请求头参数
在FastAPI中我们可以使用 Request 类来接收请求对象。
from fastapi import APIRouter,Request
router = APIRouter()
@router.post("/getRequest")
# req参数类型为Request类型。用来接收请求信息。
def getRequest(req: Request):
return {
"RequestURL":req.url, # 请求URL
"RequestIP":req.client.host, # 请求IP
"RequestHeader":req.headers, # 请求头
"RequestCookie":req.cookies, # 请求cookie
"Authorization":req.headers.get("Authorization"), # Authorization请求头
"user-agent":req.headers.get("user-agent") # user-agent请求头
}
Cookie参数
还可以通过Cookie类来获取请求头中的cookie参数。
代码示例
from fastapi import Cookie
@router.get("/get_cookie")
def get_cookie(cookie: str = Cookie(None)):
return {"cookie": cookie}请求体参数-form表单类型数据
通常情况下,GET请求是没有请求体的。因此GET请求只能携带查询参数。而POST请求等是有请求体的。
FastAPI如何接受POST请求中请求体的form表单类型数据?
需要先在FastAPI中可以使用 python-multipart 包来处理表单数据。
用法
步骤① 先安装 python-multipart 包
pip install python-multipart步骤② 使用 python-multipart 包的Form()函数获取form表单数据
# 引入Form函数
from fastapi import APIRouter,Form
router = APIRouter()
# post请求
@router.post("/login")
def login(username: str = Form(),password: str = Form()):
return {
"username":username,
"password":password
}- Form()函数会拿到请求体中的表单数据。
username: str = Form()表示参数username,类型为字符串。参数数据通过Form()函数来获取。
可以看到图中的Content-Type是application/x-www-form-urlencoded。这表示数据是Form表单数据。

请求体参数-json类型数据
通常情况下,GET请求是没有请求体的。因此GET请求只能携带查询参数。而POST请求等是有请求体的。
FastAPI如何接受POST请求中请求体的json数据?
有两种方式可以获取到请求体中的json数据。
方式1 使用 Pydantic 模型类
在FastAPI中我们可以使用pydantic包来创建数据模型类。通过数据模型类来接收请求体中的json数据。
注意:只有自定义的数据模型类继承pydantic包中的BaseModel类。才能将请求中体的json数据进行校验并传递给模型类对象。
from pydantic import BaseModel
from fastapi import APIRouter
router = APIRouter()
# 定义Addr模型类型。该类需要继承pydantic包中的BaseModel类
class Addr(BaseModel):
prpvince:str
city:str
# 定义数据模型Item类及其属性。该类需要继承pydantic包中的BaseModel类
class Item(BaseModel):
name: str
age: int = 10 # age属性设置默认值10
description: str = None # 设置为可选属性
price: float
tax: float = None # 设置为可选属性
address: Addr # 地址属性类型为Addr
# post请求
@router.post("/create_item")
# 函数参数item,数据类型为Item类。
# 该参数可以接收一个请求体数据,数据格式需要与Item类相同。
def create_item(item: Item):
return item
方式2 使用 Body 方法
在FastAPI中我们可以使用Body方法来接收请求体中的json数据。
from fastapi import APIRouter,Body
router = APIRouter()
# post请求
@router.post("/create_item")
# 函数参数name,数据类型为字符串。参数数据通过Body()函数来获取。
# Body(...) 表示参数必填,请求体中必须包含该字段。否则返回422错误。
# Body() 默认等价与 Body(...) 表示参数必填。
# Body(None) 表示参数可选,请求体参数可以不包含该字段。
def create_item(name: str = Body(...),password: str = Body(None),age: int = Body()):
return {"name":name,"password":password,"age":age}Body()方法的参数个数
当使用Body()方法接收参数时,FastAPI的行为会根据参数数量而变化。
- 当路由函数只有一个Body()参数时,FastAPI会尝试将整个请求体数据直接解析为该参数的类型。
- 当路由函数有多个Body()参数时, FastAPI会将整个请求体解析为一个JSON对象,然后从中提取对应的字段值分配给各个参数。
单个Body()参数时
问题代码: 当请求体参数为{"name":"xiaoming"}时。那么该函数会报422错误。因为name参数无法接收整个json数据
def test(name: str = Body(None)):
pass此处函数test只有一个Body()参数name。请求体数据为json格式。而name参数为字符串。FastAPI无法将整个json数据直接解析为字符串。因此会报422错误。
解决方法①:可以将参数类型设置为字典类型。从而让name参数接收整个json数据。
def test(name: dict = Body(None)):
print(name) # 此处会打印 {"name":"xiaoming"}
pass解决方法②:给Body()方法添加embed=True参数
def test(name: str = Body(None,embed=True)):
print(name) # 此处会打印 {"name":"xiaoming"}
passembed=True参数告诉FastAPI将单个参数嵌入到请求体中,而不是尝试将整个请求体解析为该参数的类型。
多个Body()参数时
# 当请求体参数为{"name":"xiaoming","age":18}时。那么该函数会正常运行。
def test(name: str = Body(None),age: int = Body(None)):
print(name) # 此处会打印 xiaoming
print(age) # 此处会打印 18
passBody()方法的几种使用方式
Body()方法以下几种使用方式。
① Body(...) 必填参数(最严格)
使用省略号...表示参数必填,请求体中必须包含该字段。
- 如果请求参数缺少该字段。会返回 422 错误。
- 如果字段值为 null(JSON 中的 null)。也会返回 422 错误(因为类型校验失败)。
示例
# phone 和 password 必须在请求体中提供
def phoneLogin(phone: str = Body(...), password: str = Body(...)):
pass② Body() 必填参数(等价于 Body(...))
如果没有提供参数,则会返回422错误。
# phone 和 password 字段必须在请求体参数中提供(与 Body(...) 效果相同)
def phoneLogin(phone: str = Body(), password: str = Body()):
pass③ Body(None) 可选参数
显式设置默认值为 None,表示参数可选,请求体参数可以不包含该字段。
- 如果请求体缺少该字段。使用默认值 None,不会报错。
- 如果请求体包含该字段但值为 null,也会接收为 None。
# address 可选,默认值为 None
def login(address: str = Body(None)):
pass④ Body("") 可选参数
显式设置默认值为空字符串,表示参数可选,请求体参数可以不包含该字段。
文件上传参数
from fastapi import File, UploadFile
@router.post("/upload_file")
def upload_file(file: UploadFile = File(...)):
return {
"filename": file.filename,
"content_type": file.content_type
}file: UploadFile = File(...)表示参数file,类型为UploadFile类。参数数据通过File()函数来获取。- UploadFile类会自动解析请求体中的文件数据。
请求参数验证和默认值
FastAPI 支持为请求参数添加验证规则和默认值。
from fastapi import Query, Path
@router.get("/items/{item_id}")
# 函数参数item_id,数据类型为整数。参数数据通过路径来获取。ge=1, le=1000 表示参数值必须在1到1000之间。description="项目ID" 表示参数的描述信息。
def read_item(
item_id: int = Path(..., ge=1, le=1000, description="项目ID"),
q: str = Query(None, min_length=3, max_length=50, description="查询字符串")
):
return {"item_id": item_id, "q": q}- Path()函数表示路径参数。ge 表示参数最小值,le表示参数最大值。descriptio 表示参数的描述信息
- Query()函数表示查询参数。min_length表示参数最小长度,max_length表示参数最大长度。
多种请求参数混合 ★★★
各种类型参数组合
FastAPI 支持在同一个函数中混合使用多种参数类型,包括查询参数、路径参数、请求体参数、Cookie参数、Header参数、文件上传参数等。
代码示例如下
@router.post("/items/{item_id}")
def create_item(
item_id: int,
query_param: str = "default",
request_data: Item = Body(...),
user_agent: str = Header(None)
):
return {
"item_id": item_id,
"query_param": query_param,
"item_name": request_data.name,
"user_agent": user_agent
}item_id: int表示路径参数item_id,类型为整数。参数数据通过路径来获取。query_param: str = "default"表示查询参数query_param,类型为字符串。参数数据通过查询参数来获取。默认值为"default"。request_data: Item = Body(...)表示请求体参数request_data,类型为Item类。参数数据通过Body()函数来获取。user_agent: str = Header(None)表示Header参数user_agent,类型为字符串。参数数据通过Header()函数来获取。默认值为None。
请求Json数据的多字段混合
在FastAPI中我们可以使用Pydantic模型类来接收请求体json数据。
但是有时候请求体json数据,不仅仅包含了Pydantic模型类中定义的属性,还包含了其他额外的字段。此时如果我们直接将请求体json数据赋值给模型类对象,会产生422 Unprocessable Entity错误。
代码示例如下
# 请求体json数据如下
{
"aaa":"123",
"bbb":"shuyx",
"ccc":"123456"
}
# dto类型如下
class Item(BaseModel):
aaa: str
aaa: str
# 路由函数如下
@router.post("/test")
def test(item: Item):
return item当发送请求体json数据给路由函数test时,会产生422 Unprocessable Entity错误。是因为请求数据中包含了Pydantic模型类中没有定义的属性ccc,从而导致函数的参数item无法解析请求体json数据。
目前有两种解决方式。
方式1
不使用 Pydantic模型类 来接受请求体json数据,直接使用字典来接受。
更改示例如下
# 请求体json数据如下
{
"aaa":"123",
"bbb":"shuyx",
"ccc":"123456"
}
# post请求
@router.post("/test")
# 函数参数aaa,数据类型为字符串。参数数据通过Body()函数来获取。
# 其他参数同理
def test(aaa: str = Body(...),bbb: str = Body(...),ccc: str = Body(...)):
return item方式2
对于这种一个请求体json数据中包含了Pydantic模型类中没有定义的属性。我们需要同时更改请求json数据和路由函数的参数。
更改示例如下
# 更改后的请求体json数据如下
{
"item":{
"aaa":"123",
"bbb":"shuyx",
},
"ccc":"123456"
}
# dto类型如下
class Item(BaseModel):
aaa: str
bbb: str
# 更改后的路由函数如下
@router.post("/test")
# ccc: str = Body(...) 表示请求体参数ccc,类型为字符串。参数数据通过Body()函数来获取。
# item: Item = Body(...) 表示请求体参数item,类型为Item类。参数数据通过Body()函数来获取。
def test(ccc: str = Body(...), item: Item = Body(...)):
return item通过将json数据分为两大部分,分别是item和ccc。item部分包含了Pydantic模型类中定义的属性。ccc部分包含了额外的字段ccc。
这样路由函数参数就可以同时获取到item和ccc两个部分的参数数据。
注意:json数据中的key必须与路由函数参数的名称一致。
422 Unprocessable Entity 错误
422 Unprocessable Entity 是一个 HTTP 状态码,表示服务器理解请求的语法,但无法处理请求的内容(参数验证失败、缺少必填字段等)
在 FastAPI 中,422 错误主要由 Pydantic 模型验证失败或参数验证失败引起。
422 错误的常见场景
- 函数参数使用 Body(...)、Query(...) 等标记为必填参数,但请求中缺少该参数。
- 函数参数中使用了单个Body()参数,但是请求体json数据中包含了1个字段。导致FastAPI无法将整个json数据直接解析为该参数类型。
- 请求中的参数类型与函数定义的类型不匹配。
- 使用 Pydantic 模型作为函数参数时,请求数据不符合 Pydantic 模型定义(缺少必填字段、字段类型错误等)。
- 参数值超出了定义的限制范围。
- 路径参数或查询参数与函数定义不匹配。
- 文件上传参数验证失败(文件类型、大小等)。
解决方式如下
- 使用 Pydantic 模型定义请求体和响应体,利用其强大的验证功能。
- 直接使用字典来接受请求体json数据。
- 对于这种一个请求体json数据中包含了Pydantic模型类中没有定义的属性。我们需要同时更改请求json数据和路由函数的参数。
FastAPI 响应
FastAPI 提供了多种响应方式,可以根据不同的场景选择合适的响应类型。
直接响应Python 对象(如字典、列表等)- 转换为Json数据
路由处理函数直接返回 Python 对象(字典、列表等),FastAPI 会自动将其转换为 JSON 数据并响应给客户端。
from fastapi import APIRouter
router = APIRouter()
@router.get("/test1")
def test1(a, b):
return {"a": a, "b": b} # 返回字典数据返回的数据格式如下
{
"a": "xxx",
"b": "xxx",
}Pydantic数据模型 - 转换为Json数据
如果路由处理函数返回一个 Pydantic 数据模型实例对象,FastAPI 会自动将其转换为 JSON 格式数据,并响应给客户端。
from fastapi import APIRouter
from pydantic import BaseModel
router = APIRouter()
# 定义 Pydantic 数据模型类。该类需要继承pydantic包中的BaseModel类。
# 并且类中的属性需要符合Pydantic数据模型的要求。
class Item(BaseModel):
name: str
description: str = None
@router.post("/items/")
def get_item(item: Item):
return item # 返回数据模型类数据返回的数据格式如下
{
"name": "xxxx",
"description": "xxxxxxx",
}Response 类 - 基础响应类
Response类是FastAPI提供的最基础的响应类,可以完全自定义响应内容、状态码和头信息。
from fastapi.responses import Response
@app.get("/raw")
async def raw_response():
return Response(
content="自定义原始内容",
media_type="text/plain",
status_code=200,
headers={"X-Custom-Header": "custom-value"}
)HTMLResponse 类 - 响应HTML内容
HTMLResponse 类用于响应HTML内容。它可以将HTML字符串作为响应体返回给客户端。
from fastapi.responses import HTMLResponse
@app.get("/html")
async def html_response():
html_content = """
<html>
<head>
<title>HTML响应示例</title>
</head>
<body>
<h1>Hello, FastAPI!</h1>
</body>
</html>
"""
return HTMLResponse(content=html_content, status_code=200)JSONResponse 类 - 响应JSON内容
JSONResponse 类用于响应JSON内容。它可以将Python对象(如字典、列表等)转换为JSON格式数据,并响应给客户端。
from fastapi.responses import JSONResponse
@app.get("/custom-json")
async def custom_json():
return JSONResponse(
status_code=201,
content={"message": "资源创建成功"},
headers={"X-Custom-Header": "value"}
)RedirectResponse类 - 重定向响应
使用 RedirectResponse类可以实现重定向响应,将客户端重定向到其他路由上。
from fastapi.responses import RedirectResponse
from pydantic import BaseModel
from fastapi import APIRouter
router = APIRouter()
@router.get("/a")
def a():
return {"a": "a"}
@router.get("/redirect")
def redirect():
return RedirectResponse(url="/a") # 重定向到/a路由上在浏览器访问/redirect路由的时候会自动跳转到 /a路由。
FileResponse 类 - 响应文件内容
FileResponse 类用于响应文件内容。它可以将文件内容作为响应体返回给客户端。
from fastapi.responses import FileResponse
import os
@app.get("/download/{filename}")
async def download_file(filename: str):
file_path = f"/path/to/files/{filename}"
if os.path.exists(file_path):
# 使用FileResponse类返回文件内容
return FileResponse(
path=file_path,
filename=filename, # 下载时的文件名
media_type="application/octet-stream"
)
return {"error": "文件不存在"}StreamingResponse 类 - 响应流式数据
StreamingResponse 类用于响应流式数据。它可以将流式数据(如生成器函数、异步迭代器等)作为响应体返回给客户端。
from fastapi.responses import StreamingResponse
import io
import time
# 定义一个生成器函数,用于模拟流式数据的生成
def generate_data():
for i in range(10):
yield f"数据块 {i}\n"
time.sleep(0.5) # 模拟处理延迟
@app.get("/stream")
async def stream_data():
# StreamingResponse类,将生成的数据作为流式响应返回
return StreamingResponse(generate_data(), media_type="text/plain")在浏览器访问/stream路由的时候,会看到类似如下的响应内容:
数据块 0
数据块 1
数据块 2
数据块 3
数据块 4响应参数
可以在路径操作装饰器中添加各种响应参数来实现各种功能。
response_class 参数 - 设置响应类
# 设置全局的默认响应类
app = FastAPI(default_response_class=JSONResponse)
# 设置该路由函数的响应类
@router.get("/html", response_class=HTMLResponse)
async def get_html():
return "<h1>HTML内容</h1>"当设置了响应类后,FastAPI会根据响应类的定义来自动处理响应数据。
response_model 参数 - 指定响应数据格式
FastAPI提供了response_model 参数。可以在路径操作装饰器中使用response_model参数来定义响应模型数据的格式。
from fastapi import FastAPI
app = FastAPI()
from pydantic import BaseModel
from fastapi import APIRouter
router = APIRouter()
# 定义类ItemA
class ItemA(BaseModel):
username: str
password: str
age: int
# 定义类ItemB
class ItemB(BaseModel):
username: str
age: int
@router.post("/getItem",response_model=ItemB)
def getItem(item: ItemA):
return item
# app应用实例中添加路由实例
app.include_router(router)item: ItemA函数形参接收的是ItemA类对象。response_model=ItemB通过给路径操作装饰器添加response_model参数。来定义响应数据格式为ItemB类。
运行结果如图所示 
在上面的代码中,定义了两个模型类ItemA和ItemB。路由处理函数getItem()接收并返回的都是ItemA类对象。但是最终的响应结果数据确是ItemB类对象。
简而言之,若路径操作装饰器中添加了response_model参数。那么FastAPI会把函数的返回值数据转换为response_model参数声明的数据类型。
response_model_exclude_unset 参数 - 去除未被赋值的响应字段
response_model_exclude_unset 参数可以去除响应模型中未被赋值的字段。即响应模型中没有被赋值的字段,不会添加到响应数据中。
@router.post("/getItem",response_model=ItemB,response_model_exclude_unset=True)
def getItem(item: ItemA):
return item函数返回的是ItemA类型的数据。但是当ItemA类型返回数据中没有被赋值的字段,不会添加到响应数据中。
response_model_include 参数 - 精细控制包含响应字段
response_model_include参数可以让你更精细地控制响应数据中包含哪些字段。
@router.post("/getItem",response_model=ItemB,response_model_include={"username", "age"})
def getItem(item: ItemA):
return item函数返回的是ItemA类型(有三个属性字段)的数据。但是response_model_include参数可以控制响应数据中只包含两个字段(username,age)的数据。
response_model_exclude 参数 - 精细控制不包含响应字段
response_model_include参数可以让你更精细地控制响应数据中不包含哪些字段。
@router.post("/getItem",response_model=ItemB,response_model_exclude={"password"})
def getItem(item: ItemA):
return item函数返回的是ItemA类型(有三个属性字段)的数据。但是response_model_include参数可以控制响应数据中排除password字段数据。
HTTPException 类 - 响应异常信息
使用 HTTPException 可以抛出异常,返回自定义的状态码和详细信息。
from fastapi import HTTPException
from fastapi import APIRouter
router = APIRouter()
@router.get("/items")
def read_item():
# 抛出HTTPException异常,参数为异常信息
raise HTTPException(status_code=404, detail="Item not found")自定义响应数据
使用 JSONResponse类 可以自定义响应数据。
from fastapi.responses import JSONResponse
from fastapi import APIRouter
router = APIRouter()
@router.get("/items/{item_id}")
def read_item(item_id: int):
content = {"item_id": item_id}
headers = {"X-Custom-Header": "custom-header-value"}
return JSONResponse(content=content, headers=headers)文件上传
当我们需要进行文件上传的时候,需要把请求的content-type设置为multipart/form-data格式。这个格式是表单文件上传格式。
下面是文件上传的两种方式。
小文件上传
使用fastapi包中的File函数来获取文件对象
from fastapi import APIRouter,File
router = APIRouter()
# 单个文件上传请求 (适合小文件上传)
@router.post("/uploadFile")
def uploadFile(file: bytes = File()):
return {
"fileLength":len(file) # 文件字节大小
}
# 多个文件上传请求 (适合小文件上传)
@router.post("/uploadFiles")
def uploadFiles(files: list[bytes] = File()):
return {
"fileCount":len(files) # 文件个数
}- File函数用来获取上传文件的数据。
file: bytes = File()设置一个file参数,类型为字节数据类型。数据从File函数获取。
注意:这种方式是一次性读取文件数据内存中,因此这种方式只适合小文件上传。对于大文件上传需要用其他方法。
大文件上传 (推荐)
使用fastapi包中的UploadFile函数来获取文件对象。
from fastapi import APIRouter,UploadFile
router = APIRouter()
# 单个文件上传请求
@router.post("/uploadFile")
def uploadFile(file: UploadFile):
return {
"fileSize":file.size, # 文件大小
"fileName":file.filename # 文件名称
}
# 多个文件上传请求
@router.post("/uploadFiles")
def uploadFiles(files: list[UploadFile]):
# 打印文件其他信息
for i in files:
print("fileName",i.filename)
print("fileSize",i.size)
return {
"fileCount":len(files) # 文件个数
}file: UploadFile设置一个file参数,是UploadFile类型。
通过UploadFile函数,我们还可以获取文件名称和大小等其他信息。

FastAPI 访问静态文件
我们可以在FastAPI应用中开放一个静态文件目录。通过这个目录来专门访问FastAPI应用中的静态文件。
- 在
main.py文件编写如下代码
from fastapi import FastAPI
from fastapi.staticfiles import StaticFiles
app = FastAPI()
# FastAPI应用实例对象 挂载静态目录
app.mount("/statics",StaticFiles(directory="statics"))- 先导入fastapi.staticfiles包中的StaticFiles类。
StaticFiles(directory="statics")设置statics目录为静态文件目录。之后挂载到FastAPI应用实例对象app上。- 注意:静态文件目录和代码文件之间的相对路径。
- 然后创建statics目录。其中创建一个txt文件
- 浏览器访问静态文件。

