fastapi学习笔记
1.库安装
>> pip install "fastapi[standard]"
2.快速入门
- (1) 编写测试代码
main.py
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/")
def read_root():
return {"Hello": "World"}
@app.get("/items/{item_id}")
def read_item(item_id: int, q: Union[str, None] = None):
return {"item_id": item_id, "q": q}
- (2) 启动当前服务:
>> fastapi dev main.py
FastAPI Starting development server 🚀
Searching for package file structure from directories with __init__.py files
Importing from /home/mirror/workspace/python
module 🐍 main.py
code Importing the FastAPI app object from the module with the following code:
from main import app
app Using import string: main:app
server Server started at http://127.0.0.1:8000
server Documentation at http://127.0.0.1:8000/docs
tip Running in development mode, for production use: fastapi run
Logs:
INFO Will watch for changes in these directories: ['/home/mirror/workspace/python']
INFO Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO Started reloader process [12766] using WatchFiles
INFO Started server process [12769]
INFO Waiting for application startup.
INFO Application startup complete.
- (3) 测试服务:网页分别输入如下地址:
http://127.0.0.1:8000
http://127.0.0.1:8000/items/1180
3.路径参数
3.1 简单路径参数
你可以使用 python
格式字符串相同语法,来声明路径“参数”或“变量”。
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id):
return {"item_id": item_id}
路径参数的值 item_id
将会作为参数 item_id
传递给你的函数,所以,你可以运行这个示例,然后访问 http://127.0.0.1:8000/items/foo
,你将看到如下响应:
{"item_id": "foo"}
3.2 有类型的路径参数
你可以使用标准 python
类型声明,在函数中声明路径参数类型:
from fastapi import FastAPI
app = FastAPI
@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}
这里将 item_id
声明为 int
类型,编辑器将会支持在你的函数内部进行错误检查及代码补全等。与此同时,当你进行类型声明后,FastAPI
会自动帮你进行请求解析,若请求的传参类型不对,将会给你报一个 HTTP
错误。
3.3.顺序问题
路径操作是按照顺序来进行的,例如,你期望 /users/me
匹配优先级高于 /user/{usr_id}
,你就需要将 /users/me
相关函数写到 /user/{user_id}
前面:
from fastapi import FastAPI
app = FastAPI
@app.get("/user/me")
async def read_user_me():
return {"user_id": "the current user"}
@app.get("/user/{user_id}")
async def read_user(user_id: str):
return {"user_id": user_id}
类似的,你不能重定义路径操作。
3.4.预定义值
你可以使用标准 python
的 Enum
来预定义可能的有效路径参数值。具体操作如下:
- (1) 创建子类继承自
str
和Enum
; - (2) 通过继承自
str
,表明值必须是str
类型; - (3) 创建具有固定值的类属性,这些固定值将是可用的有效值;
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from enum import Enum
from fastapi import FastAPI
class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"
app = FastAPI()
@app.get("/models/{model_name}")
async def get_model(model_name: ModelName):
if model_name is ModelName.alexnet:
return {"model_name": model_name, "message": "Deep Learning FTW!"}
if model_name.value == "lenet":
return {"model_name": model_name, "message": "LeCNN all the images"}
return {"model_name": model_name, "message": "Have some residuals"}
这里使用 is
对传入参数与枚举成员 ModelName
进行比较,然后使用 model_name.value
来获取实际值。
4.查询参数
4.1 默认查询参数解析
当你的声明不属于路径参数的其它函数参数时,它们会被自动解释为“查询”参数。
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI
app = FastAPI()
fake_items_db = [{"item_name": "Foo"}, {"item_name", "Bar"}, {"item_name", "Baz"}]
@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
print(f"skip: {skip}, limit: {limit}")
return fake_items_db[skip : skip + limit]
访问网页 http://127.0.0.1:8000/items/?skip=0&limit=20
,查询被设置为 ?
后面的键值对,并通过 &
符号进行分隔。当你不传参数时,查询参数为默认值 skip=0, limit=10
。
4.2 可选参数
相同的方式,你可以通过设置它们默认值为 None
来声明可选查询参数:
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int = 0, q: Union[str, None] = None):
print(f"item_id: {item_id}, q: {q}")
if q:
return {"item_id": item_id, "q": q}
return {"item_id": item_id}
访问 URL:http://127.0.0.1:8000/items/1160?q=hello,world
4.3 必须查询参数
当你为为非路径参数声明默认值时,它就不是必须的,当你想将一个参数声明为必须时,只需要不给它任何默认值:
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from typing import Union
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: str, needy: str):
return {"item_id": item_id, "needy": needy}
访问 URL: http://127.0.0.1:8000/items/item_id=123456?needy=Hi
5.请求主体
当需要从客户端发送数据到 API
,你需要将数据作为请求 body
来发送。一个请求 body
为从客户端发送到 API
的数据,一个响应 body
为从 API
发送到客户端的数据。
你的 API
几乎总是需要发送响应 body
,但客户端不必一直发送请求 body
,有时它们仅需要请求一个路径,可能带一些请求参数,而不需要发送 body
。
你需要将你的数据模型声明为继承自 BaseModel
的类,然后,使用标准的 Python
类型声明其所有属性:
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI
from pydantic import BaseModel
from typing import Union
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
app = FastAPI()
@app.post("/items/")
async def create_item(item: Item):
item_dict = item.model_dump()
if item.tax:
price_with_tax = item.price + item.tax
item_dict.update({'price_with_tax': price_with_tax})
return item_dict
访问方法:
- (1) 命令行:
curl
工具
curl -X 'POST' \
'http://127.0.0.1:8000/items/' \
-H 'Content-Type: application/json' \
-d '{
"name": "Example Item",
"description": "This is an example item",
"price": 9.99,
"tax": 1.0
}'
- (2)
Postman
:请求方法设置为POST
,地址设置为http://127.0.0.1:8000/items
,Body
设置为raw
,类型设置为JSON
,内容如下:
{
"name": "Example Item",
"description": "This is an example item",
"price": 9.99,
"tax": 1.0
}
点击 Send
,响应如下:
{
"name": "Example Item",
"description": "This is an example item",
"price": 9.99,
"tax": 1.0,
"price_with_tax": 10.99
}
6.请求参数和字符串校验
FastAPI
允许你为参数声明附加信息和校验,让我们先看一个例子:
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI
from typing import Union
app = FastAPI()
@app.get("/items/")
async def create_item(q: Union[str, None] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
print(f"q: {q}")
results.update({"q": q})
return results
请求参数 q
的类型为 Union[str, None]
,意味着它的类型可以为 str
也可以为 None
,默认值为 None
,所以 FastAPI
将知道它不是必须要传的。
6.1 附加校验
即使 q
是可选的,但是只要附加校验——“提供它的长度不能超过50个字符”,我们都将强制执行。
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI, Query
from typing import Union
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def create_item(q: Annotated[Union[str, None], Query(max_length=50)] = None):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
print(f"q: {q}")
results.update({"q": q})
return results
当添加附加校验后,FastAPI
将会做如下内容:
- (1) 校验数据,并确保数据最大长度为50个字符长度;
- (2) 当数据未通过校验,会向客户端显示一个明确的错误;
- (3) 在
OpenAPI
路径操作中记录参数(会将其显示在自动文档UI
中);
旧版本中要求使用 Query
作为参数默认值:
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI, Query
from typing import Union
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def create_item(q: Union[str, None] = Query(default=None, max_length=10)):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
print(f"q: {q}")
results.update({"q": q})
return results
这种情况下(不使用 Annotated
),必须替换在函数中使用 Query()
替换掉缺省值 None
,我们现在需要使用参数 Query(default=None)
来设置缺省值。
但是 Query
版本显式地声明它作为 query
参数,然后我们传递更多参数给 Query
,这种情况下,max_length
参数被用于字符串:
q: Union[str, None] = Query(default=None, max_length=50)
使用 Annotated
的优势:
- (1) 函数参数的默认值是实际默认值,对于
python
来说,通常更加直观; - (2) 你可以在无需
FastAPI
的地方调用相同函数,它将按预期工作。如果有一个必需参数(无默认值),你的编辑器将会报一个错误,Python
也会告知你,在运行它时没有传递必需参数; - (3) 当你不使用
Annotated
而使用旧的默认值风格,如果你在其它无需FastAPI
的地方调用函数,你必须记住将参数传递给函数以使其正常工作,否则值将与你预期不同(例如,QueryInfo
或类似值,而不是str
)。并且,你的编辑器也不会报错,Python
也不会在运行时报错,只要在内部出错时才会报错。
6.2 添加更多校验
你也可以添加一个参数 min_length
,定义一个参数需要匹配的正则表达式 pattern
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI, Query
from typing import Union
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def create_item(
q: Annotated[
Union[str, None],
Query(min_length=3, max_length=50, pattern="^fixedquery$")
] = None
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
print(f"q: {q}")
results.update({"q": q})
return results
这个特殊正则表达式将会检查接收到参数值:
^
:以下面字符开始,之前没有字符;fixedquery
:具有精确的值fixedquery
;$
:到此结束,之后不再有任何字符fixedquery
;
6.3 必填参数
还有另外一种方法声明参数是必需传的,你只需要将默认值设置未 ...
:
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI, Query
from typing import Union
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def create_item(
q: Annotated[
Union[str, None],
Query(min_length=3, max_length=50, pattern="^fixedquery$")
] = ...
):
results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
if q:
print(f"q: {q}")
results.update({"q": q})
return results
6.4 参数列表及缺省值
当你定义查询参数时,Query
还可以声明接收值列表及默认值:
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI, Query
from typing import Union, List
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def create_item(
q: Annotated[
Union[List[int], None],
Query(
title="Query int list",
description="Query int for the items to search database that have a good match"
)
] = [123, 456]
):
query_items = {"q": q}
return query_items
当你访问 http://127.0.0.1:8000/items/
,对应响应为:
{
"q": [
123,
456
]
}
你也可以使用 list
,而不是 List[int]
,但是 List[int]
会检查列表内容是否为整数,而 list
单独使用不会。你还可以添加更多参数,如 description
,title
等。
6.5 别名函数
当你想要参数是 item-query
,但是 item-query
不是一个有效的 Python
变量,你可以使用 alias
,该别名将用于查找参数值:
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI, Query
from typing import Union, List
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def create_item(
q: Annotated[
Union[str, None],
Query(
alias="item-query"
)
] = None
):
query_items = {"q": q}
return query_items
请求 URL
为:http://127.0.0.1:8000/items/?item-query=mirror
,最终输出结果为:
{
"q": "mirror"
}
6.6 弃用参数
假设不想要某个参数,但是由于有些客户端正在用它而不得不保留,因此想要在文档中明确的表示它为弃用的。你可以向 Query
中传参 deprecated=True
:
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI, Query
from typing import Union, List
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/")
async def create_item(
q: Annotated[
Union[str, None],
Query(
alias="item-query",
deprecated=True
)
] = None
):
query_items = {"q": q}
return query_items
打开页面 127.0.0.1:8000/docs
,你会看到当前参数被有红色的标注 depreated
。你也可以使用 Query
的 include_in_schema
参数来标注某个参数是否 OpenAPI
文档中展示。
7.路径参数和数字校验
相同的方式,你可以使用 Query
为查询参数声明更多验证和元数据,你可以使用 Path
声明相同类型的验证和元数据.
7.1 导入Path
首先,从 fastapi
中导入 Path
,并导入 Annotated
:
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI, Query, Path
from typing import Union, List
from typing_extensions import Annotated
7.2 声明元数据
你可以像 Query
一样声明所有相同参数,例如,为路径参数 item_id
声明一个 title
元数据
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI, Query, Path
from typing import Union, List
from typing_extensions import Annotated
app = FastAPI()
@app.get("/items/{item_id}")
async def create_item(
item_id: Annotated[
int, Path(title="The ID of the item to get")
],
q: Annotated[
Union[str, None],
Query(alias="item-query")
] = None
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
访问 URL
:http://127.0.0.1:8000/items/2025?item-query=mirror
,输出结果为:
{
"item_id": 2025,
"q": "mirror"
}
当参数必须作为路径的一部分,一个路径参数通常是必需的。就算你将其声明为 None
或设置一个默认值,这也不起任何作用,它将仍然被需要。
7.3 按需排列参数
如果你使用 Annotated
,这可能不那么重要或必要。将 *
作为函数的第一个参数,对于 *
符号 Python
不会做任何事,但是,它将知道所有后续参数应该作为关键字参数(键值对)被调用:
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI, Path
from typing import Union
app = FastAPI()
@app.get("/items/{item_id}")
async def create_item(*,
item_id: int = Path(title="The ID of the item to get"),
q: Union[str, None] = None,
v: Union[str, None] = None
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
if v:
results.update({"v": v})
return results
这样请求时,就无需去在意传参顺序,参数会按照字典进行解析,无论你访问时按照 http://127.0.0.1:8000/items/2025?v=mirror&q=yu
访问,还是按照 http://127.0.0.1:8000/items/2025?q=yu&v=mirror
都能得到正确结果。当然,使用 Annotated
会更好,当没有使用函数参数默认值,你将没有这个问题,你可能也无需使用 *
。
7.4 数字验证
使用 Query
和 Path
(和其它参数),你可以声明数字约束,这里使用 ge=1
,item_id
将需要为一个大于等于(greater equal
)1:
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI, Path
from typing import Union
app = FastAPI()
@app.get("/items/{item_id}")
async def create_item(*,
item_id: int = Path(title="The ID of the item to get", ge=1),
q: str
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
return results
当你访问过程中传入 item_id
小于1时,例如:http://127.0.0.1:8000/items/0?q=1024
就会报错:
{"detail":[{"type":"greater_than_equal","loc":["path","item_id"],"msg":"Input should be greater than or equal to 1","input":"0","ctx":{"ge":1}}]}
相同的,你可以使用其它约束:
gt
:greater than
ge
:greater equal
lt
:less than
le
:less equal
8.主体内容
8.1 混合 Path
,Query
和主体参数
首先,你可以自由地混合 Path
,Query
和请求主体参数声明,FastAPI
将知道做什么。你也可以通过设置主体参数默认值为 None
,将其设置为可选项:
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI, Path
from typing import Union
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
@app.put("/items/{item_id}")
async def create_item(*,
item_id: int = Path(title="The ID of the item to get", ge=1),
q: Union[str, None] = None,
item: Union[Item, None] = None
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
if item:
results.update({"item": item})
return results
测试方法:使用 Postman
将方法设置为 PUT
,地址设置为 http://127.0.0.1:8000/items/100?q=mirroryu
,Body
模式设置为 raw
,数据格式设置为 JSON
,内容设置为:
{
"name": "Example Item",
"description": "This is an example item",
"price": 9.99,
"tax": 1.0
}
点击 Send
可以得到下面结果:
{
"item_id": 100,
"q": "mirroryu",
"item": {
"name": "Example Item",
"description": "This is an example item",
"price": 9.99,
"tax": 1.0
}
}
8.2 多个主体参数
你可以声明多个主体参数,例如 item
和 user
:
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI, Path
from typing import Union
from pydantic import BaseModel
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
class User(BaseModel):
username: str
full_name: Union[str, None] = None
@app.put("/items/{item_id}")
async def create_item(*,
item_id: int = Path(title="The ID of the item to get", ge=1),
q: Union[str, None] = None,
item: Union[Item, None] = None,
user: Union[User, None] = None
):
results = {"item_id": item_id}
if q:
results.update({"q": q})
if item:
results.update({"item": item})
if user:
results.update({'user': user})
return results
测试方法和上面一样,不过主体内容需要更改如下:
{
"item": {
"name": "Example Item",
"description": "This is an example item",
"price": 9.99,
"tax": 1.0
},
"user": {
"username": "mirror",
"full_name": "chenjingyu"
}
}
输出结果为:
{
"item_id": 100,
"q": "mirroryu",
"item": {
"name": "Example Item",
"description": "This is an example item",
"price": 9.99,
"tax": 1.0
},
"user": {
"username": "mirror",
"full_name": "chenjingyu"
}
}
8.3 主体中的奇异值
Query
和 Path
可以为请求和路径参数来定义额外数据,同样的,FastAPI
提供了等效的 Body
。例如,扩展先前的模型,在相同主体中,除了 item
和 user
外,你可能想要有另外一个键 importance
,如果使用默认声明的方式,FastAPI
会将其视为请求与参数,这时,你需要使用另外一个关键字 Body
:
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI, Path, Body
from typing import Union
from pydantic import BaseModel
from typing_extensions import Annotated
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
class User(BaseModel):
username: str
full_name: Union[str, None] = None
@app.put("/items/{item_id}")
async def create_item(*,
item_id: int = Path(title="The ID of the item to get", ge=1),
q: Union[str, None] = None,
item: Item,
user: User,
importance: Annotated[
int, Body()
]
):
results = {"item_id": item_id, "importance": importance}
if q:
results.update({"q": q})
if item:
results.update({"item": item})
if user:
results.update({'user': user})
return results
请求的 Body
内容设置如下:
{
"item": {
"name": "Example Item",
"description": "This is an example item",
"price": 9.99,
"tax": 1.0
},
"user": {
"username": "mirror",
"full_name": "chenjingyu"
},
"importance": 30
}
PUT
结果如下:
{
"item_id": 100,
"importance": 30,
"q": "mirroryu",
"item": {
"name": "Example Item",
"description": "This is an example item",
"price": 9.99,
"tax": 1.0
},
"user": {
"username": "mirror",
"full_name": "chenjingyu"
}
}
8.4 嵌入单个主体参数
假设你只有一个 Pydantic model
格式 Item
类型的 item
主体参数,默认情况下,FastAPI
会直接假设它为主体参数,但是,如果你希望它接收一个带有键 item
的 Json
(内部包含 model
内容),就像声明额外的主体参数一样,你可以使用特殊 Body
参数 embed
:
item: Item = Body(enbed=True)
例如:
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI, Path, Body
from typing import Union
from pydantic import BaseModel
from typing_extensions import Annotated
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = None
price: float
tax: Union[float, None] = None
@app.put("/items/{item_id}")
async def create_item(*,
item_id: int = Path(title="The ID of the item to get", ge=1),
item: Annotated[Item, Body(embed=True)],
):
results = {"item_id": item_id, "item": item}
return results
那么请求的主体内容需要写成:
{
"item": {
"name": "Example Item",
"description": "This is an example item",
"price": 9.99,
"tax": 1.0
}
}
而不是:
{
"name": "Example Item",
"description": "This is an example item",
"price": 9.99,
"tax": 1.0
}
8.5 字段信息
你可以使用 Query,Path和Body
在路径操作函数参数中声明附加验证和元数据,同样的,你也可以使用 Pydantic
的 Field
来声明 Pydantic
模型内部的校验和元数据。
'''
Author: chenjingyu
Date: 2024-12-24 15:38:23
Contact: 2458006466@qq.com
Description: main
'''
from fastapi import FastAPI, Path, Body
from typing import Union
from pydantic import BaseModel, Field
from typing_extensions import Annotated
app = FastAPI()
class Item(BaseModel):
name: str
description: Union[str, None] = Field(
default=None, title="The description of the item", max_length=300
)
price: float = Field(gt=0, description="The price must be greater than zero")
tax: Union[float, None] = None
@app.put("/items/{item_id}")
async def create_item(*,
item_id: int = Path(title="The ID of the item to get", ge=1),
item: Annotated[Item, Body(embed=True)],
):
results = {"item_id": item_id, "item": item}
return results
对模型属性使用 Field
,可以为模型属性添加附加约束或元数据,Filed
和 Query
,Path
及 Body
工作方式类似,它们有相同的参数。