路径操作 #
路径操作装饰器 #
基本语法 #
python
@app.get('/path')
def handler():
return {'message': 'Hello'}
支持的 HTTP 方法 #
text
┌─────────────────────────────────────────────────────────────┐
│ HTTP 方法装饰器 │
├─────────────────────────────────────────────────────────────┤
│ │
│ @app.get() 读取资源 │
│ @app.post() 创建资源 │
│ @app.put() 更新资源(完整替换) │
│ @app.patch() 更新资源(部分更新) │
│ @app.delete() 删除资源 │
│ @app.options() 获取支持的 HTTP 方法 │
│ @app.head() 获取响应头 │
│ @app.trace() 跟踪路径 │
│ │
└─────────────────────────────────────────────────────────────┘
装饰器参数 #
python
@app.get(
'/items/{item_id}',
response_model=Item,
status_code=200,
tags=['items'],
summary='Get an item',
description='Get a specific item by ID',
response_description='The requested item',
deprecated=False,
)
def read_item(item_id: int):
return {'item_id': item_id}
路由顺序 #
python
# 正确:具体路径在前
@app.get('/users/me')
def read_users_me():
return {'user_id': 'current_user'}
@app.get('/users/{user_id}')
def read_user(user_id: str):
return {'user_id': user_id}
# 错误:通配路径在前会匹配所有
# @app.get('/users/{user_id}') # 会匹配 /users/me
# def read_user(user_id: str):
# return {'user_id': user_id}
路径参数 #
基本使用 #
python
@app.get('/items/{item_id}')
def read_item(item_id: int):
return {'item_id': item_id}
类型转换 #
python
@app.get('/items/{item_id}')
def read_item(item_id: int): # 自动转换为整数
return {'item_id': item_id}
@app.get('/users/{user_id}')
def read_user(user_id: str): # 字符串类型
return {'user_id': user_id}
@app.get('/items/{item_id}/price')
def read_item_price(item_id: int, price: float): # 浮点数
return {'item_id': item_id, 'price': price}
@app.get('/items/{item_id}/active')
def read_item_active(item_id: int, active: bool): # 布尔值
return {'item_id': item_id, 'active': active}
路径参数验证 #
python
from fastapi import Path
@app.get('/items/{item_id}')
def read_item(
item_id: int = Path(
...,
title='Item ID',
description='The ID of the item to retrieve',
ge=1,
le=1000
)
):
return {'item_id': item_id}
验证约束 #
text
┌─────────────────────────────────────────────────────────────┐
│ 路径参数验证约束 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 数值类型: │
│ gt 大于 ge 大于等于 │
│ lt 小于 le 小于等于 │
│ │
│ 字符串类型: │
│ min_length 最小长度 │
│ max_length 最大长度 │
│ regex 正则表达式 │
│ │
│ 示例: │
│ item_id: int = Path(..., ge=1, le=100) │
│ name: str = Path(..., min_length=2, max_length=50) │
│ │
└─────────────────────────────────────────────────────────────┘
枚举路径参数 #
python
from enum import Enum
class ModelName(str, Enum):
alexnet = 'alexnet'
resnet = 'resnet'
lenet = 'lenet'
@app.get('/models/{model_name}')
def get_model(model_name: ModelName):
return {'model_name': model_name, 'value': model_name.value}
包含路径的参数 #
python
@app.get('/files/{file_path:path}')
def read_file(file_path: str):
return {'file_path': file_path}
访问 /files/home/johndoe/myfile.txt:
json
{"file_path": "home/johndoe/myfile.txt"}
查询参数 #
基本使用 #
python
@app.get('/items/')
def read_items(skip: int = 0, limit: int = 10):
return {'skip': skip, 'limit': limit}
访问 /items/?skip=20&limit=30:
json
{"skip": 20, "limit": 30}
必需查询参数 #
python
@app.get('/items/')
def read_items(skip: int, limit: int): # 没有默认值,必需
return {'skip': skip, 'limit': limit}
可选查询参数 #
python
from typing import Optional
@app.get('/items/{item_id}')
def read_item(item_id: str, q: Optional[str] = None):
if q:
return {'item_id': item_id, 'q': q}
return {'item_id': item_id}
查询参数验证 #
python
from fastapi import Query
@app.get('/items/')
def read_items(
q: Optional[str] = Query(
None,
min_length=3,
max_length=50,
regex='^[a-zA-Z]+$'
)
):
return {'q': q}
必需查询参数验证 #
python
@app.get('/items/')
def read_items(
q: str = Query(
...,
min_length=3,
description='Search query string'
)
):
return {'q': q}
默认值查询参数 #
python
@app.get('/items/')
def read_items(
q: str = Query('default', min_length=3)
):
return {'q': q}
查询参数列表 #
python
@app.get('/items/')
def read_items(q: list[str] = Query([])):
return {'q': q}
访问 /items/?q=foo&q=bar:
json
{"q": ["foo", "bar"]}
查询参数别名 #
python
@app.get('/items/')
def read_items(
q: Optional[str] = Query(None, alias='item-query')
):
return {'q': q}
访问 /items/?item-query=foo。
弃用参数 #
python
@app.get('/items/')
def read_items(
q: Optional[str] = Query(
None,
alias='item-query',
deprecated=True
)
):
return {'q': q}
参数组合 #
路径参数 + 查询参数 #
python
@app.get('/users/{user_id}/items/{item_id}')
def read_user_item(
user_id: int,
item_id: str,
q: Optional[str] = None,
short: bool = False
):
item = {'item_id': item_id, 'owner_id': user_id}
if q:
item.update({'q': q})
if not short:
item.update({'description': 'Long description'})
return item
多种参数混合 #
python
from fastapi import FastAPI, Path, Query
@app.get('/items/{item_id}')
def read_item(
item_id: int = Path(..., title='Item ID', ge=1),
q: Optional[str] = Query(None, min_length=3),
size: float = Query(1.0, gt=0, lt=10.5)
):
return {'item_id': item_id, 'q': q, 'size': size}
请求体 #
定义请求体模型 #
python
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: Optional[str] = None
price: float
tax: Optional[float] = None
@app.post('/items/')
def create_item(item: Item):
return item
请求体 + 路径参数 + 查询参数 #
python
@app.put('/items/{item_id}')
def update_item(
item_id: int,
item: Item,
q: Optional[str] = None
):
result = {'item_id': item_id, **item.model_dump()}
if q:
result.update({'q': q})
return result
多个请求体参数 #
python
class Item(BaseModel):
name: str
price: float
class User(BaseModel):
username: str
full_name: Optional[str] = None
@app.put('/items/{item_id}')
def update_item(item_id: int, item: Item, user: User):
return {'item_id': item_id, 'item': item, 'user': user}
请求体格式:
json
{
"item": {
"name": "Foo",
"price": 45.2
},
"user": {
"username": "john",
"full_name": "John Doe"
}
}
单个值请求体 #
python
from fastapi import Body
@app.put('/items/{item_id}')
def update_item(
item_id: int,
item: Item,
importance: int = Body(...)
):
return {'item_id': item_id, 'item': item, 'importance': importance}
嵌入单个请求体 #
python
@app.put('/items/{item_id}')
def update_item(item_id: int, item: Item = Body(..., embed=True)):
return {'item_id': item_id, 'item': item}
请求体格式:
json
{
"item": {
"name": "Foo",
"price": 45.2
}
}
表单数据 #
接收表单数据 #
python
from fastapi import FastAPI, Form
app = FastAPI()
@app.post('/login/')
def login(username: str = Form(...), password: str = Form(...)):
return {'username': username}
文件上传 #
python
from fastapi import FastAPI, File, UploadFile
app = FastAPI()
@app.post('/files/')
def create_file(file: bytes = File(...)):
return {'file_size': len(file)}
@app.post('/uploadfile/')
def create_upload_file(file: UploadFile):
return {'filename': file.filename}
多文件上传 #
python
@app.post('/files/')
def create_files(files: list[bytes] = File(...)):
return {'file_sizes': [len(file) for file in files]}
@app.post('/uploadfiles/')
def create_upload_files(files: list[UploadFile]):
return {'filenames': [file.filename for file in files]}
请求头和 Cookie #
请求头 #
python
from fastapi import FastAPI, Header
app = FastAPI()
@app.get('/items/')
def read_items(user_agent: Optional[str] = Header(None)):
return {'User-Agent': user_agent}
带下划线的请求头 #
python
@app.get('/items/')
def read_items(
x_token: Optional[str] = Header(None, convert_underscores=True)
):
return {'X-Token': x_token}
Cookie #
python
from fastapi import FastAPI, Cookie
app = FastAPI()
@app.get('/items/')
def read_items(ads_id: Optional[str] = Cookie(None)):
return {'ads_id': ads_id}
响应状态码 #
设置状态码 #
python
from fastapi import FastAPI, status
app = FastAPI()
@app.post('/items/', status_code=201)
def create_item(name: str):
return {'name': name}
@app.delete('/items/{item_id}', status_code=status.HTTP_204_NO_CONTENT)
def delete_item(item_id: int):
return None
常用状态码 #
text
┌─────────────────────────────────────────────────────────────┐
│ HTTP 状态码 │
├─────────────────────────────────────────────────────────────┤
│ │
│ 2xx 成功 │
│ 200 OK 请求成功 │
│ 201 Created 资源创建成功 │
│ 204 No Content 成功但无返回内容 │
│ │
│ 4xx 客户端错误 │
│ 400 Bad Request 请求格式错误 │
│ 401 Unauthorized 未认证 │
│ 403 Forbidden 无权限 │
│ 404 Not Found 资源不存在 │
│ 422 Unprocessable 验证失败 │
│ │
│ 5xx 服务器错误 │
│ 500 Internal Error 服务器内部错误 │
│ 503 Service Unavailable 服务不可用 │
│ │
└─────────────────────────────────────────────────────────────┘
下一步 #
现在你已经掌握了路径操作,接下来学习 请求体,深入了解 FastAPI 的数据验证机制!
最后更新:2026-03-29