0%

FastAPI自学教程(22) - 请求表单模型

1. 基础表单模型声明

1
2
3
4
5
6
7
8
9
10
11
12
13
from typing import Annotated
from fastapi import FastAPI, Form
from pydantic import BaseModel

app = FastAPI()

class FormData(BaseModel):
username: str
password: str

@app.post("/login/")
async def login(data: Annotated[FormData, Form()]):
return data
  • 必须安装 python-multipart 依赖:pip install python-multipart
  • 使用 Form() 显式声明表单模型参数,支持 FastAPI 0.113.0+ 版本
  • Pydantic 模型字段自动映射表单参数,支持复杂数据验证

2. 字段验证与配置

1
2
3
4
5
class StrictForm(BaseModel):
model_config = {"extra": "forbid"}

username: str = Field(min_length=4, max_length=20)
password: str = Field(regex="^(?=.*[A-Za-z])(?=.*\d)[A-Za-z\d]{8,}$")
  • model_config = {"extra": "forbid"} 禁止未声明字段(FastAPI 0.114.0+)
  • 支持 Field 参数实现字段级验证(如正则表达式、长度限制)
  • 客户端发送额外字段时返回 422 错误(如 extra 字段)

3. 多版本兼容写法

1
2
3
4
5
6
7
8
9
10
11
# Python 3.8+ 兼容写法
from typing_extensions import Annotated

@app.post("/login/")
async def login(data: Annotated[FormData, Form()]):
return data

# 旧版非Annotated写法
@app.post("/login/")
async def login(data: FormData = Form()):
return data
  • 优先推荐使用 Annotated 注解方式(Python 3.10+)
  • 旧版本需使用 Union 类型声明可选字段
  • 支持统一校验规则跨版本兼容

4. 文档与错误处理

1
2
3
@app.post("/login/", response_model=FormData)
async def login(...):
...
  • Swagger UI 自动生成表单字段说明
  • 错误响应示例:
    1
    2
    3
    4
    5
    6
    7
    {
    "detail": [{
    "type": "extra_forbidden",
    "loc": ["body", "extra"],
    "msg": "Extra inputs are not permitted"
    }]
    }
  • 支持交互式文档测试(需手动设置 application/x-www-form-urlencoded

5. 高级应用场景

1
2
3
4
5
6
7
8
9
10
11
@app.post("/complex-form/")
async def complex_form(
file: UploadFile = File(...),
form_data: Annotated[FormData, Form()],
metadata: str = Form(...)
):
return {
"filename": file.filename,
"user": form_data.username,
"meta": metadata
}
  • 支持文件上传与表单数据混合处理
  • 可通过 request.form() 获取原始表单数据
  • 生产环境建议启用 HTTPS 传输敏感数据

注意事项

  1. 表单字段名需与 HTML 表单的 name 属性完全一致
  2. 使用 Depends() 实现模型依赖注入
  3. 推荐配合 response_model 控制响应数据结构
  4. 生产环境应使用真正的密码哈希算法(如 Argon2)