本文基于Datawhale的开源学习项目wow-fullstac的子项目FastAPI
如果文中出现了错误以及不理解的地方欢迎在留言
请求体
也许直接说请求体
三个字会感觉很别扭,header
叫做请求头
,所以请求体
其实就是跟在它后面的东西了
FastAPI 使用请求体从客户端(例如浏览器)向 API 发送数据。请求体是客户端发送给 API 的数据。响应体
是 API 发送给客户端的数据。API 基本上肯定要发送响应体,但是客户端不一定发送请求体。
摘自FastAPI关于请求体的介绍
在这个例子中,构造了如何计算物品的总价值并且返回的函数
import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
total_price = item.price + item.tax
return {**item.model_dump(), "total_price": total_price}
if __name__ == "__main__":
uvicorn.run(app)
构造一个请求体
import requests
url = 'http://127.0.0.1:8000/items/'
data = {
"name": "apple",
"description": "big red apple.",
"price": 9.99,
"tax": 5.01,
}
response = requests.post(url,json=data)
print(response.text)
执行结果
{"name":"apple","description":"big red apple.","price":9.99,"tax":5.01,"total_price":15.0}
路径参数、查询参数和请求体参数的异同点
特性 | 路径参数 | 查询参数 | 请求体参数 |
---|---|---|---|
位置 | URL路径的一部分 | URL查询字符串 | 请求体(例如JSON或表单数据) |
形式 | /items/{item_id} | /items?id=123&name=abc | JSON、XML、表单数据等 |
必需性 | 必须提供(通常用于资源标识) | 可选(用于过滤、排序等) | 可选(通常用于复杂数据传输) |
用途 | 定位资源 | 修改请求行为(筛选、排序等) | 传递复杂数据 |
数据类型 | 字符串或数字(通常用于ID等) | 字符串或数字(通常用于查询) | 任意数据格式(如JSON) |
示例 | /items/123 | /items?id=123&name=abc | 请求体中的JSON数据 |
FastAPI映射 | Path() | Query() | Body() |
补充
查询参数和字符串校验
将 Query
用作查询参数的默认值即可添加校验条件
原始版本async def read_names(name: str | None = None)
带校验的版本async def read_names(name: str | None = Query(default=原始默认值,校验条件1,校验条件2,等等))
如果想要强制声明他是个必选条件参数,用...
来代替原始默认值
即可,也可以直接写条件不写默认值
Annotated
会告诉fastapi后面的条件怎么进行校验
from typing import Annotated
@app.get("/names/")
async def read_names(name: Annotated[str,Query(min_length=3, max_length=20)]):
result = [{"name": "Tom"}, {"name": "Alice"}]
if name:
result.append({"name": name})
return result
- 验证限制:
gt
,ge
,lt
,le
,min_length
,max_length
,regex
等,用于字段值的范围和格式验证。 - 描述和文档:
title
,description
,example
,examples
,openapi_examples
用于生成清晰的API文档。
这些配置项使得FastAPI能够提供强大的字段验证、文档生成以及灵活的API设计功能。
访问http://127.0.0.1:8000/names/
{
"detail": [
{
"type": "missing",
"loc": [
"query",
"name"
],
"msg": "Field required",
"input": null
}
]
}
访问http://127.0.0.1:8000/names/?name=alex
[
{
"name": "Tom"
},
{
"name": "Alice"
},
{
"name": "alex"
}
]
访问http://127.0.0.1:8000/names/?name=al
{
"detail": [
{
"type": "string_too_short",
"loc": [
"query",
"name"
],
"msg": "String should have at least 3 characters",
"input": "al",
"ctx": {
"min_length": 3
}
}
]
}
我想一次查询多个值怎么办
查询参数列表/多个值
from typing import List
@app.get("/names/")
async def read_names(names: Annotated[List[str], Query(min_length=2, max_length=20)]):
result = [{"name": "Tom"}, {"name": "Alice"}]
if names:
for name in names:
result.append({"name": name})
return result
访问http://127.0.0.1:8000/names/?names=alex&names=bob&names=jack
注意此时min_length
代指了list至少需要添加两个元素
[
{
"name": "Tom"
},
{
"name": "Alice"
},
{
"name": "alex"
},
{
"name": "bob"
},
{
"name": "jack"
}
]
路径参数校验
与查询参数校验类似的,我们自然也可以对路径参数进行校验
只需要对路径参数进行Path
校验
@app.get("/names/{name}")
async def read_names(name: Annotated[str, Path(min_length=2, max_length=20)]):
result = [{"name": "Tom"}, {"name": "Alice"}]
if name:
result.append({"name": name})
return result
访问http://127.0.0.1:8000/names/a
{
"detail": [
{
"type": "string_too_short",
"loc": [
"path",
"name"
],
"msg": "String should have at least 2 characters",
"input": "a",
"ctx": {
"min_length": 2
}
}
]
}
多个请求体参数
现在让我们把Path
Query
和请求体
一起使用,对于下面的例子,我们需要构造的请求体需要同时包含Item
User
import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
class Buyer(BaseModel):
buyername: str
location: str | None = None
@app.put("/items/{item_name}")
async def update_item(item_name: str, item: Item, buyer: Buyer):
results = {"item_name": item_name, "item": item, "buyer": buyer}
return results
if __name__ == "__main__":
uvicorn.run(app)
构造请求体
import requests
url = 'http://127.0.0.1:8000/items/apple'
data = {
"item": {"name": "apple", "description": "Big red apple", "price": 15, "tax": 5},
"buyer": {"buyername": "Jack", "location": "the DC"},
}
response = requests.put(url,json=data)
print(response.text)
结果
'{"item_name":"apple","item":{"name":"apple","description":"Big red apple","price":15.0,"tax":5.0},"buyer":{"buyername":"Jack","location":"the DC"}}'
请求体中的单一值
还是上面的例子,假设我们还需要单独判断一下是不是苹果成熟的季节,类似的我们有Body()
来校验它
import uvicorn
from fastapi import FastAPI, Body
from pydantic import BaseModel
from typing import Annotated
app = FastAPI()
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: float | None = None
class Buyer(BaseModel):
buyername: str
location: str | None = None
@app.put("/items/{item_name}")
async def update_item(
item_name: str,
item: Item,
buyer: Buyer,
month: Annotated[int, Body(ge=6, le=12, title="It's time to eat apple!")],
):
results = {"item_name": item_name, "item": item, "buyer": buyer}
return results
if __name__ == "__main__":
uvicorn.run(app)
构造请求体
import requests
url = 'http://127.0.0.1:8000/items/apple'
data = {
"item": {"name": "apple", "description": "Big red apple", "price": 15, "tax": 5},
"buyer": {"buyername": "Jack", "location": "the DC"},
"month":5
}
response = requests.put(url,json=data)
print(response.text)
结果
{"detail":[{"type":"greater_than_equal","loc":["body","month"],"msg":"Input should be greater than or equal to 6","input":5,"ctx":{"ge":6}}]}
声明模型属性
如果我想对tax
进行限制该怎么做?
模型隶属于pydantic
我们自然需要从中引入校验Field
用法与Path
Query
一致,不再过多赘述
from pydantic import Field
class Item(BaseModel):
name: str
description: str | None = None
price: float
tax: Annotated[float,Field(le=100)]
Cookie/Header参数
与Path
Query
用法一致
from typing import Annotated
from fastapi import Cookie, FastAPI
app = FastAPI()
@app.get("/items/")
async def read_items(ads_id: Annotated[str | None, Cookie()] = None):
return {"ads_id": ads_id}
访问``