Skip to content

Commit fde439f

Browse files
committed
fastapi parameters post
1 parent a5b1b43 commit fde439f

File tree

27 files changed

+914
-1275
lines changed

27 files changed

+914
-1275
lines changed
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
+++
2+
date = '2025-08-06T10:30:00+08:00'
3+
draft = false
4+
title = 'FastAPI Parameters'
5+
+++
6+
FastAPI 是一个现代、快速(高性能)的 Python Web 框架, 它自动处理参数的解析、验证和文档生成
7+
8+
本文将介绍 FastAPI 中三类最常用的参数: **路径参数(Path Parameters)****查询参数(Query Parameters)****请求体(Request Body)**的用法与原理
9+
10+
11+
12+
13+
### 1. Path Parameters 路径参数
14+
路径参数是 URL 路径中的动态部分, 使用 `{}` 包裹表示
15+
```python
16+
from fastapi import FastAPI
17+
18+
app = FastAPI()
19+
20+
@app.get("/items/{item_id}")
21+
async def read_item(item_id: str):
22+
return {"item_id": item_id}
23+
```
24+
访问 `/items/foo` 返回:
25+
```python
26+
{"item_id": "foo"}
27+
```
28+
29+
#### Data conversion & validation 类型声明与自动转换
30+
可以为路径参数声明类型, FastAPI 会自动解析并验证:
31+
```python
32+
@app.get("/items/{item_id}")
33+
async def read_item(item_id: int):
34+
return {"item_id": item_id}
35+
```
36+
访问 `/items/3`, `item_id` 会被转换为 int 类型
37+
38+
#### Routing orders 路由匹配顺序
39+
路径匹配按声明顺序执行, 例如
40+
```python
41+
@app.get("/users/me")
42+
async def read_user_me():
43+
return {"user_id": "current_user"}
44+
45+
@app.get("/users/{user_id}")
46+
async def read_user(user_id: str):
47+
return {"user_id": user_id}
48+
```
49+
必须先声明 `/users/me`, 否则会被 `/users/{user_id}` 捕获
50+
51+
52+
#### Predefined enum values
53+
使用 Python 的 `Enum` 定义一组可选的路径参数值
54+
```python
55+
from enum import Enum
56+
57+
class ModelName(str, Enum):
58+
alexnet = "alexnet"
59+
resnet = "resnet"
60+
lenet = "lenet"
61+
62+
@app.get("/models/{model_name}")
63+
async def get_model(model_name: ModelName):
64+
return {"model_name": model_name}
65+
```
66+
Swagger 文档会自动显示可选值
67+
68+
69+
#### Path parameters containing paths 路径型参数
70+
默认路径参数不能包含斜杠 `/`, 但可以用 `:path` 声明允许匹配完整路径
71+
```python
72+
@app.get("/files/{file_path:path}")
73+
async def read_file(file_path: str):
74+
return {"file_path": file_path}
75+
```
76+
访问 `/files/home/user/file.txt`, `file_path` 会是 `"home/user/file.txt"`
77+
78+
79+
80+
81+
### 2. Query Parameters 查询参数
82+
查询参数是 URL `?` 后的键值对, 不属于路径部分
83+
```python
84+
fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}]
85+
86+
@app.get("/items/")
87+
async def read_items(skip: int = 0, limit: int = 10):
88+
return fake_items_db[skip : skip + limit]
89+
```
90+
访问 `/items/?skip=0&limit=10` 时, 会自动把查询参数 `skip``limit` 转成 `int`
91+
92+
#### Optional parameters 可选参数默认值
93+
给查询参数赋默认值即为可选
94+
```python
95+
@app.get("/items/{item_id}")
96+
async def read_item(item_id: str, q: str | None = None):
97+
if q:
98+
return {"item_id": item_id, "q": q}
99+
return {"item_id": item_id}
100+
```
101+
`q` 是可选查询参数, 默认为 `None`
102+
103+
#### Query parameter type conversion 查询参数类型转换
104+
```python
105+
@app.get("/items/{item_id}")
106+
async def read_item(item_id: str, q: str | None = None, short: bool = False):
107+
...
108+
```
109+
支持自动把字符串转换成布尔值, 以下都会被识别为 `True`
110+
```
111+
http://127.0.0.1:8000/items/foo?short=1
112+
```
113+
或者
114+
- `?short=true`
115+
- `?short=on`
116+
- `?short=yes`
117+
118+
#### Multiple path and query parameters 多路径查询参数组合
119+
路径参数和查询参数可混合使用, 无需声明顺
120+
```python
121+
@app.get("/users/{user_id}/items/{item_id}")
122+
async def read_user_item(user_id: int, item_id: str, q: str | None = None, short: bool = False):
123+
...
124+
```
125+
126+
#### Required query parameters 必填查询参数
127+
未设置默认值的查询参数为必填参数
128+
```python
129+
@app.get("/items/{item_id}")
130+
async def read_item(item_id: str, needy: str):
131+
...
132+
```
133+
上面的 `needy` 就是一个必填的 `str` 类型
134+
135+
当然也可以定义一些必填参数, 以及有默认值的可选参数
136+
```python
137+
@app.get("/items/{item_id}")
138+
async def read_user_item(
139+
item_id: str, needy: str, skip: int = 0, limit: int | None = None
140+
):
141+
...
142+
```
143+
- `needy` & `item_id`, 必填 `str` 类型
144+
- `skip`, 默认值为 0 的类型
145+
- `limit`, 一个可选的类型
146+
147+
[]
148+
- 路径参数永远是必填的, 因为它们来自 URL 本身
149+
```python
150+
@app.get("/items/{item_id}")
151+
def read(item_id: str = "123"): # 这里写默认值是无效的
152+
...
153+
```
154+
- 类型为 `Optional[...]``type | None` 不等于可选参数, 仍然要配合默认值 `= None` 才是可选
155+
```python
156+
def func(x: int | None): # 必填
157+
def func(x: int | None = None): # 可选
158+
```
159+
160+
161+
162+
163+
### 3. Request Body
164+
当通过 API 传送数据的时候, 通常通过 request body 发送
165+
166+
request body 是 client 客户端发送给 API 的数据, 而 response body 是 API 发送给 client 的数据
167+
168+
#### Pydantic's BaseModel
169+
使用 Pydantic 定义数据模型
170+
```python
171+
from fastapi import FastAPI
172+
from pydantic import BaseModel
173+
174+
class Item(BaseModel):
175+
name: str
176+
description: str | None = None
177+
price: float
178+
tax: float | None = None
179+
180+
app = FastAPI()
181+
182+
@app.post("/items/")
183+
async def create_item(item: Item):
184+
return item
185+
```
186+
187+
#### Declare it as a parameter
188+
在路由中声明请求体
189+
```python
190+
@app.post("/items/")
191+
async def create_item(item: Item):
192+
return item
193+
```
194+
FastAPI 会:
195+
- 读取 request body, 并转换为 JSON
196+
- 校验字段和类型
197+
- 返回类型错误时给出详细反馈, 包括数据那里以及导致了什么错误
198+
- 提供编辑器类型提示
199+
- 生成模型的 JSON Schema 定义, 也可以在项目中任何位置使用
200+
- 根据 schema 自动生成文档
201+
202+
#### Request body + path + query parameters 路径参数、查询参数与请求体同时使用
203+
```python
204+
@app.put("/items/{item_id}")
205+
async def update_item(item_id: int, item: Item, q: str | None = None):
206+
result = {"item_id": item_id, **item.dict()}
207+
if q:
208+
result.update({"q": q})
209+
return result
210+
```
211+
这个函数参数会被以下方式识别:
212+
- 如果参数同时在 path 中声明, 被当成 path parameter
213+
- 如果参数为单一类型, 如 `int`, `float`, `str``bool` 等, 将会被解释为 query parameter
214+
- 如果参数声明为一个 Pydantic Model, 将被解释为 request body

content/posts/how-fastapi-works.zh-cn.md

Lines changed: 0 additions & 161 deletions
This file was deleted.

content/posts/microservice-apis.zh-cn.md

Lines changed: 0 additions & 5 deletions
This file was deleted.

0 commit comments

Comments
 (0)