前言
FastAPI 教程:将 Python 函数封装为 API。
Operating System: Ubuntu 22.04.4 LTS
将 Python 函数封装为 API
1. FastAPI 简介
FastAPI 是一个现代、快速(高性能)的 Web 框架,用于基于 Python 3.7+ 标准类型注解的 API 构建。它具有自动生成文档、类型检查、异步支持等优点。
2. 安装 FastAPI 和 Uvicorn
pip install fastapi uvicorn
3. 快速入门:Hello World
main.py
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"message": "Hello World"}
运行:
uvicorn main:app --reload
说明:
FastAPI()
:创建 FastAPI 应用实例。@app.get("/")
:声明 GET 方法的路由。read_root()
:处理根路径请求,返回 JSON。
4. 路由与参数
4.1 路径参数
@app.get("/items/{item_id}")
def read_item(item_id: int):
return {"item_id": item_id}
item_id: int
:自动类型转换和校验。
4.2 查询参数
@app.get("/users/")
def read_user(name: str, age: int = 18):
return {"name": name, "age": age}
name
:必填查询参数。age
:有默认值,选填。
5. 请求体与 Pydantic 模型
5.1 定义数据模型
from pydantic import BaseModel
class Item(BaseModel):
name: str
price: float
tags: list[str] = []
5.2 POST 请求体
@app.post("/items/")
def create_item(item: Item):
return {"item": item}
item: Item
:自动解析 JSON 请求体为 Pydantic 对象。
6. 文件上传与多参数处理
6.1 文件上传
from fastapi import File, UploadFile
@app.post("/uploadfile/")
async def upload_file(file: UploadFile = File(...)):
content = await file.read()
return {"filename": file.filename, "size": len(content)}
UploadFile
:高效处理大文件,支持异步读取。File(...)
:声明为文件参数。
6.2 混合参数(文件+表单+查询)
from fastapi import Form
@app.post("/process/")
async def process_file(
file: UploadFile = File(...),
threshold: float = Form(...),
user_id: int = Form(...)
):
content = await file.read()
# 假设这里处理文件内容
result = len(content) * threshold + user_id
return {"result": result}
Form(...)
:声明表单参数(适合前端 multipart/form-data 提交)。
7. 封装 Python 函数为 API
7.1 假设有如下函数
def analyze_file(content: bytes, threshold: float, user_id: int) -> dict:
# 这里是你的业务逻辑
length = len(content)
score = length * threshold + user_id
return {"length": length, "score": score}
7.2 封装为 API
@app.post("/analyze/")
async def analyze_endpoint(
file: UploadFile = File(...),
threshold: float = Form(...),
user_id: int = Form(...)
):
content = await file.read()
result = analyze_file(content, threshold, user_id)
return result
8. 复杂对象参数(JSON)
8.1 定义对象
class Config(BaseModel):
threshold: float
user_id: int
options: dict
8.2 接收 JSON 对象
@app.post("/analyze_with_config/")
async def analyze_with_config(
file: UploadFile = File(...),
config: Config = Form(...)
):
content = await file.read()
# 这里 config 是字符串,需要解析
import json
config_data = Config.parse_raw(config)
result = analyze_file(content, config_data.threshold, config_data.user_id)
return result
注意:如果前端用 multipart/form-data 发送文件和 JSON,需要将 JSON 作为字符串传递。
9. 完整示例:支持多种参数类型
main.py
from fastapi import FastAPI, File, UploadFile, Form
from pydantic import BaseModel
import json
app = FastAPI()
def analyze_file(content: bytes, threshold: float, user_id: int, options: dict) -> dict:
length = len(content)
score = length * threshold + user_id + sum(options.values())
return {"length": length, "score": score, "options": options}
class Config(BaseModel):
threshold: float
user_id: int
options: dict
@app.post("/analyze/")
async def analyze_endpoint(
file: UploadFile = File(...),
config: str = Form(...)
):
content = await file.read()
config_data = Config.parse_raw(config)
result = analyze_file(content, config_data.threshold, config_data.user_id, config_data.options)
return result
前端请求示例(Python requests):
import requests
import json
url = "http://127.0.0.1:8000/analyze/"
files = {"file": open("test.txt", "rb")}
config = {
"threshold": 1.5,
"user_id": 42,
"options": {"a": 10, "b": 20}
}
data = {"config": json.dumps(config)}
response = requests.post(url, files=files, data=data)
print(response.json())
10. 详细函数说明
FastAPI 相关
FastAPI()
:创建应用实例。@app.post("/analyze/")
:声明 POST 路由。async def analyze_endpoint(...)
:异步视图函数,处理请求。UploadFile = File(...)
:声明文件上传参数。Form(...)
:声明表单参数。BaseModel
:用于数据校验和自动文档。
业务函数
analyze_file(content, threshold, user_id, options)
:业务逻辑处理函数,接收文件内容和参数,返回结果字典。
数据模型
Config(BaseModel)
:定义参数结构,自动校验和解析。
解析 JSON
Config.parse_raw(config)
:将字符串解析为 Pydantic 对象。
11. 自动文档
访问 http://127.0.0.1:8000/docs
可查看自动生成的 Swagger UI 文档,方便测试和调试。
12. 进阶:响应模型、异常处理、依赖注入等
- 响应模型:
@app.post(..., response_model=ResultModel)
- 异常处理:
from fastapi import HTTPException
- 依赖注入:
Depends
总结
本教程详细介绍了 FastAPI 的基本用法、参数类型、文件上传、对象参数、函数封装等内容。你可以根据自己的业务需求,灵活扩展和组合这些用法。
FastAPI 中的 Form
1. 作用
Form
用于声明表单数据类型的请求参数。
当客户端(如网页、移动端、Postman)以 application/x-www-form-urlencoded
或 multipart/form-data
格式提交数据时,FastAPI 通过 Form
来接收这些参数。
2. 典型用法
from fastapi import FastAPI, Form
app = FastAPI()
@app.post("/login/")
def login(username: str = Form(...), password: str = Form(...)):
return {"username": username, "password": password}
说明
Form(...)
:声明该参数从表单数据中获取,...
表示必填。username: str = Form(...)
:username
参数会从表单字段中提取。password: str = Form(...)
:同理。
3. 适用场景
- 前端 HTML
<form>
表单提交数据。 - 需要和文件上传(
File
)一起混合提交数据时。 - 需要接收
application/x-www-form-urlencoded
或multipart/form-data
格式的数据时。
4. 与 Body/Query 的区别
Body
:用于接收 JSON 格式的请求体。Query
:用于接收 URL 查询参数。Form
:用于接收表单数据(通常是 POST/PUT 请求)。
5. 结合文件上传
from fastapi import FastAPI, File, UploadFile, Form
app = FastAPI()
@app.post("/upload/")
async def upload(
file: UploadFile = File(...),
description: str = Form(...),
user_id: int = Form(0)
):
content = await file.read()
return {
"filename": file.filename,
"description": description,
"user_id": user_id,
"size": len(content)
}
说明
description
和user_id
都是表单字段。file
是上传的文件。- 这种混合方式常用于前端上传文件时附带额外参数。
6. Form 的参数
default
:默认值,...
表示必填。alias
:别名,前端字段名与后端参数名不一致时可用。title
、description
、example
等:用于自动文档。
示例:
from fastapi import Form
def endpoint(
name: str = Form(..., title="姓名", description="用户的姓名", example="张三")
):
...
总结
Form
用于接收表单数据。- 常用于前端表单、文件上传等场景。
- 只能用于 POST/PUT 等带请求体的方法。
- 支持类型注解、默认值、文档说明等。
FastAPI 中的 Query
1. 作用
Query
用于声明查询参数(即 URL 中 ?key=value
形式的参数)。
它可以设置参数的默认值、校验规则、文档说明等。
2. 典型用法
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
def read_items(
q: str = Query(None, min_length=3, max_length=50, description="搜索关键字")
):
return {"q": q}
说明
q: str = Query(None, ...)
:q
是一个查询参数,默认值为None
。min_length=3
、max_length=50
:限制字符串长度。description
:用于自动文档。
3. 适用场景
- 需要接收 URL 查询参数时(如
/items/?q=abc
)。 - 需要对参数进行校验、设置默认值、生成文档时。
4. Query 的常用参数
参数 | 作用说明 |
---|---|
default | 默认值,... 表示必填 |
alias | 别名(URL 参数名与函数参数名不一致时用) |
title | 文档标题 |
description | 文档描述 |
min_length | 最小长度(字符串) |
max_length | 最大长度(字符串) |
regex | 正则表达式校验(字符串) |
ge | 最小值(数值) |
le | 最大值(数值) |
gt | 大于(数值) |
lt | 小于(数值) |
example | 示例值 |
示例
from fastapi import Query
def endpoint(
page: int = Query(1, ge=1, description="页码,必须大于等于1"),
size: int = Query(10, le=100, description="每页数量,最大100"),
keyword: str = Query(None, min_length=2, max_length=20, description="搜索关键字")
):
...
5. 多值查询参数
如果一个参数可以多次出现在 URL 中(如 /items/?tag=python&tag=fastapi
),可以这样声明:
from typing import List
@app.get("/items/")
def read_items(tags: List[str] = Query([])):
return {"tags": tags}
6. 必填查询参数
将默认值设为 ...
(省略号)即可:
@app.get("/search/")
def search(q: str = Query(..., description="必填搜索关键字")):
return {"q": q}
7. 使用 alias
如果 URL 参数名和函数参数名不一致:
@app.get("/users/")
def get_user(user_id: int = Query(..., alias="id")):
return {"user_id": user_id}
请求 /users/?id=123
时,user_id
会被赋值为 123。
总结
Query
用于声明和校验查询参数。- 支持类型注解、默认值、校验规则、文档说明等。
- 常用于 GET 请求的参数接收和校验。
- 支持多值、必填、别名等高级用法。
FastAPI 中的 Body
1. 作用
Body
用于声明请求体参数,即客户端以 JSON、XML、或其他格式发送到服务器的数据。
在 FastAPI 中,通常配合 Pydantic 模型使用,接收和校验复杂的结构化数据(如 JSON 对象)。
2. 典型用法
from fastapi import FastAPI, Body
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
price: float
@app.post("/items/")
def create_item(item: Item = Body(...)):
return {"item": item}
说明
item: Item = Body(...)
:item
参数会从请求体中解析,必须是 JSON 格式,...
表示必填。Item(BaseModel)
:定义请求体的数据结构和类型校验。
3. 适用场景
- 客户端以 JSON 格式发送数据(如 POST/PUT 请求)。
- 需要接收复杂对象或嵌套结构的数据。
- 需要对请求体参数进行详细校验和文档说明。
4. Body 的常用参数
参数 | 作用说明 |
---|---|
default | 默认值,... 表示必填 |
embed | 是否嵌套请求体(见下方说明) |
title | 文档标题 |
description | 文档描述 |
example | 示例值 |
示例
from fastapi import Body
@app.post("/users/")
def create_user(
name: str = Body(..., title="用户名", description="用户的名字", example="张三"),
age: int = Body(18, ge=0, le=120, description="年龄")
):
return {"name": name, "age": age}
5. 多个 Body 参数
FastAPI 支持多个 Body 参数,但需要用 Body(...)
明确声明:
@app.post("/login/")
def login(
username: str = Body(...),
password: str = Body(...)
):
return {"username": username}
注意:如果不加 Body(...)
,FastAPI 会把参数当作查询参数。
6. embed 参数
如果你想让请求体的 JSON 结构为 { "item": { ... } }
,可以用 embed=True
:
@app.post("/items/")
def create_item(item: Item = Body(..., embed=True)):
return {"item": item}
此时,客户端应发送:
{
"item": {
"name": "apple",
"price": 3.5
}
}
7. Body 与 Pydantic 模型
Body 通常与 Pydantic 模型配合,自动完成类型校验、文档生成、数据解析。
总结
Body
用于声明请求体参数,常用于 POST/PUT 等方法。- 支持类型注解、默认值、嵌套、文档说明等。
- 通常与 Pydantic 模型配合,接收和校验复杂 JSON 数据。
embed=True
可控制 JSON 结构嵌套。
结语
第三百四十一篇博文写完,开心!!!!
今天,也是充满希望的一天。