Python:FastAPI的typing.Annotated参数校验示例

官方文档说明:typing ------ 对类型提示的支持 --- Python 3.11.15 文档

python 复制代码
#!/Users/mac/.pyenv/versions/3.11.8/bin/python3
#coding=utf-8

from fastapi import FastAPI,Query,Path,Body,Form,UploadFile,File,HTTPException
from pydantic import BaseModel,Field,model_validator
from typing import Annotated,List,Optional

#uv run fastapi dev main.py

app = FastAPI()

#用途1:查询参数校验,如用于 GET 请求中的查询参数(URL 中的 ?key=value 部分)
#特点:支持长度、范围、正则等校验、可设置默认值、自动集成到文档中
#curl -X GET http://127.0.0.1:8000/search?keyword=tom&limit=100
#output:{"keyword":"tom","limit":100}
@app.get("/search")
def search(
        keyword:Annotated[str,Query(min_length=2,max_length=50)],
        limit:Annotated[int, Query(gt=0, le=100)] = 10
):
    return {"keyword": keyword, "limit":limit}

#用途2:路径参数校验,用于 URL 路径中的变量参数(如 /user/{user_id})
#特点:适用于必须出现在 URL 中的参数;同样支持字符串长度;正则匹配等校验规则
#curl -X GET http://127.0.0.1:8000/user/tom
@app.get("/user/{name}")
def get_user(name:Annotated[str, Path(min_length=3, max_length=10)]):
    return {"name":name}


#用途3:请求体校验:Body + Pydantic 模型
#特点:使用 Pydantic 模型定义数据结构;支持嵌套字段、列表、可选字段等复杂结构;自动处理类型转换与验证错误反馈;更细粒度地控制每个字段的格式、范围;支持默认值、可选字段等特性;
#name:字符串,必填;price:浮点数,必须 > 0;tags:字符串数组,可选
# curl -X POST "http://127.0.0.1:8000/items" \
#   -H "Content-Type: application/json" \
#   -d '{
#     "name": "iPhone 17",
#     "username": "tom",
#     "age": 30,
#     "email": "tom@example.com",
#     "price": 5999.00,
#     "tags": ["手机", "苹果", "电子产品"]
#   }'
# curl -X POST "http://127.0.0.1:8000/items" \
#   -H "Content-Type: application/json" \
#   -d '{"name":"iPhone 17","username":"tom","age":30,"price":5999}'
class Item(BaseModel): #Pydantic Model
    name:str
    username:Annotated[str, Field(min_length=3, max_length=20)]
    age:Annotated[int, Field(ge=0, le=120)]
    email:Optional[str]=None
    price:Annotated[float, Field(gt=0)]
    tags:List[str]=[]

@app.post("/items")
def create_item(item:Annotated[Item, Body()]):
    return item

#用途4:表单数据校验,HTML 表单提交的数据,可以使用 Form 来校验 application/x-www-form-urlencoded 格式的数据
#curl -X POST "http://127.0.0.1:8000/login" \
#  -d "username=tom" \
#  -d "password=123456"
@app.post("/login")
def login(username:Annotated[str, Form(min_length=3)],password:Annotated[str, Form(min_length=6)]):
    return {"username":username, "password":password}

ALLOWED_CONTENT_TYPES = {
    "image/jpeg",
    "image/png",
    "image/gif",
}

MAX_FILE_SIZE = 2 * 1024 * 1024  # 2MB

#用途5:文件上传校验: UploadFile + File FastAPI 还支持对上传文件进行类型、大小等限制
#curl -X POST "http://127.0.0.1:8000/upload" \
#  -F "file=@/Users/mac/Desktop/testabc.jpg"
@app.post("/upload")
async def upload_file(
    file: Annotated[UploadFile, File()]
):
    if file.content_type not in ALLOWED_CONTENT_TYPES:
        raise HTTPException(
            status_code=400,
            detail="只允许上传 JPEG、JPG、PNG、GIF 图片"
        )

    if file.size is not None and file.size > MAX_FILE_SIZE:
        raise HTTPException(
            status_code=400,
            detail="文件大小不能超过 2MB"
        )

    return {
        "filename": file.filename,
        "content_type": file.content_type,
        "size": file.size,
    }

#用途6:复杂逻辑校验, 使用Pydantic 的 model_validator 或 field_validator
#curl -X POST "http://127.0.0.1:8000/check-password" \
#  -H "Content-Type: application/json" \
#  -d '{
#    "password": "123456",
#    "confirm_password": "123456"
#  }'
class CheckPassword(BaseModel):
    password: Annotated[
        str,
        Field(min_length=6, max_length=32)
    ]

    confirm_password: Annotated[
        str,
        Field(min_length=6, max_length=32)
    ]

    @model_validator(mode="after")
    def check_passwords(self):
        if self.password != self.confirm_password:
            raise ValueError("密码两次输入不一致")

        return self


@app.post("/check-password")
def check_password(data: CheckPassword):
    return {
        "message": "密码验证成功"
    }
相关推荐
千里码aicood2 小时前
fastAPI-儿童智能陪伴交互系统设计
交互·fastapi
卷无止境4 小时前
FastAPI 的可观测性进化,从打日志到看清整个系统的呼吸
后端·python·fastapi
虎虎(_ _)。゜zzZ4 小时前
FastAPI-lifespan生命周期管理实战
mysql·aigc·fastapi·大模型部署·lifespan·python异步
卷无止境4 小时前
FastAPI 的 CI/CD 之路,从代码提交到线上运行
后端·python·fastapi
Broccoli523026652 天前
FastAPI 与跨域资源共享 CROS
fastapi
Gain_chance2 天前
大数据毕业设计实战|Data Insight Platform:用 FastAPI + ClickHouse 打造低门槛全链路数据洞察平台
大数据·数据库·clickhouse·毕业设计·fastapi
逆风飞翔的小叔3 天前
【Python基础】FastAPI 从入门到项目实战操作详解
fastapi·fastapi 详解·fastapi 使用详解·fastapi 请求参数详解·fastapi 总结
卷无止境4 天前
当FastAPI遇上机器学习,一个脚手架工具能省下多少工夫
后端·python·fastapi
练习两年半的攻城狮4 天前
【RAG实战】知识库 BGE-M3 稀疏向量混合检索方案
python·fastapi·llamaindex