00341 FastAPI教程


前言

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-urlencodedmultipart/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-urlencodedmultipart/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)
    }

说明

  • descriptionuser_id 都是表单字段。
  • file 是上传的文件。
  • 这种混合方式常用于前端上传文件时附带额外参数。

6. Form 的参数

  • default:默认值,... 表示必填。
  • alias:别名,前端字段名与后端参数名不一致时可用。
  • titledescriptionexample 等:用于自动文档。

示例:

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=3max_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 结构嵌套。

结语

第三百四十一篇博文写完,开心!!!!

今天,也是充满希望的一天。


文章作者: LuYF-Lemon-love
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 LuYF-Lemon-love !
  目录