- ASGI入门笔记:ASGI入门
- FastAPI入门一:FastAPI路径操作函数与响应
- FastAPI入门二:FastAPI路径参数与查询参数
内容小记:
- 路径参数Path Parameter使用(类型验证与转换、包含
/
的文件路径、预定义值,Annotated使用与int范围限定) - 查询参数Query Parameter使用(默认值、可选参数、类型验证与转换、Annotated使用与str格式限定)
注:本文所有代码在python3.11下验证
路径参数(Path Parameter)
路径参数或变量 可以使用与Python格式化字符串相同的语法来声明:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def item(item_id):
return {"item_id": item_id}
而后就可以通过 127.0.0.1/items/1+1=10 进行访问。浏览器显示内容如下:
{
"item_id": "1+1=10"
}
类型验证与转换
上面的例子中,item_id
内容比较随意。借助FastAPI底层使用的Pydantic,可以指定类型(比如int
):
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/{item_id}")
async def item(item_id: int):
return {"item_id": item_id}
此时用浏览器访问 127.0.0.1/items/1+1=10,将会遇到错误
{
"detail": [
{
"type": "int_parsing",
"loc": [
"path",
"item_id"
],
"msg": "Input should be a valid integer, unable to parse string as an integer",
"input": "1+1=10",
"url": "https://errors.pydantic.dev/2.5/v/int_parsing"
}
]
}
而 127.0.0.1/items/1 将会看到正确的结果
{
"item_id": 1
}
同样,试图访问 127.0.0.1/items/1.2 也会将会看到错误的结果,要兼容int和float,需要改为
@app.get("/items/{item_id}")
async def item(item_id: float):
return {"item_id": item_id}
这些校验工作都是由Pydantic
完成的。
顺序
使用路径操作函数时,如果由固定路径需要处理。要确保先声明固定路径:
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/1+1=10")
async def item0():
return {"item_id": "1+1=10"}
@app.get("/items/{item_id}")
async def item(item_id: float):
return {"item_id": item_id}
文件路径(路径转换符)
如果要提取 127.0.0.1:8000/files/aa/bb.txt
中的路径aa\bb.txt
怎么办?
这么写是不行的
from fastapi import FastAPI
app = FastAPI()
@app.get("/files/{fp}")
async def get_file(fp):
return {"file": fp}
需要像下面这样,指定转换符path
,提取变量才能包含/
符号:
from fastapi import FastAPI
app = FastAPI()
@app.get("/files/{fp:path}")
async def get_file(fp):
return {"file": fp}
限定字符串取值(预定值)
如何限定,只允许路径变量取几个特定值,比如部门,只能在hr、finance、rd中选择。
首先想到的是,这么尝试:
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/departments/{department_name}")
async def deal_with_department(department_name):
if department_name not in ["hr", "finance", "rd"]:
raise HTTPException(status_code=404, detail="Department not found")
return {"name": department_name}
工作起来没问题,不存在的部门直接报404异常。
不过,FastAPI中是这么用的:
from enum import Enum
from fastapi import FastAPI, HTTPException
app = FastAPI()
class DepartmentName(str, Enum):
hr = "hr"
finance = "finance"
rd = "rd"
@app.get("/departments/{department_name}")
async def deal_with_department(department_name : DepartmentName):
return {"name": department_name}
使用Enum的好处是,通过127.0.0.1:8000\docs
访问文档时,更友好:
限定路径参数值范围
如何要确保有效的路径参数值大小10~100之间,该怎么办?
- https://fastapi.tiangolo.com/reference/parameters/
FastAPI利用的python中的Annotated功能,来给类型增加注解信息:
from fastapi import FastAPI, Path
from typing import Annotated
app = FastAPI()
@app.get("/items/{item_id}")
async def get_item(item_id: Annotated[int, Path(title="The ID of the item to get", ge=10, le=100)]):
return {"item": item_id}
127.0.0.1/items/1
无效127.0.0.1/items/101
无效127.0.0.1/items/20
有效
注意:注解信息中用的Path,注意和下面查询参数中的Query区分
查询参数(Query Parameter)
查询参数是键值对,位于URL的
?
之后。不同的参数用&
进行分隔。
FastAPI的处理逻辑是:路径处理函数中声明的参数,如果不是路径参数,将自动解释为查询参数。
获取查询参数
比如,要获取 127.0.0.1:8001/items/?item_id=111
中的查询参数,可以:
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/items/")
async def get_item(item_id: int):
return {"item": item_id}
默认值
查询参数可以指定默认值,比如item_id: int = 1
:
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/items/")
async def get_item(item_id: int = 1):
return {"item": item_id}
这样一来,下面两个写法等价:
127.0.0.1:8001/items/
127.0.0.1:8001/items/?item_id=1
可选参数
注意与默认值概念区分。将默认值设置为None
来声明可选查询参数:
@app.get("/items/")
async def get_item(item_id: int | None = None):
if item_id:
return {"item": item_id}
return "items"
这样一来:
127.0.0.1:8001/items/
127.0.0.1:8001/items/?item_id=1
不再等价。
注意:
|
说明item_id
可以是int,也可以是None类型。
类型校验与转换
比如,下面的例子:我们定义参数bool类型:
from fastapi import FastAPI, HTTPException
app = FastAPI()
@app.get("/items/{item_id}")
async def get_item(item_id, d: bool):
item = {"item_id": item_id}
if d:
item.update({"description": "Demo from 1+1=10"})
return item
下面的都是等价的:
127.0.0.1:8001/items/111?d=1
127.0.0.1:8001/items/111?d=on
127.0.0.1:8001/items/111?d=yes
127.0.0.1:8001/items/111?d=true
127.0.0.1:8001/items/111?d=True
- ...
注意:0 对应False,1对应True。其他数字不会转成bool。
字符串验证
如何要确保有效的查询参数的长度在3~10之间,该怎么办?
FastAPI利用的python中的Annotated功能,来给类型增加注解信息(注意,对于查询参数,用的Query):
from fastapi import FastAPI, Query
from typing import Annotated
app = FastAPI()
@app.get("/items/")
async def get_item(item_id: Annotated[str, Query(max_length=10, min_length=3)]):
return {"item": item_id}
127.0.0.1:8001/items/?item_id=1
无效127.0.0.1:8001/items/?item_id=11111111111111111111
无效127.0.0.1:8001/items/?item_id=1111
有效
使用Annotated注解时,依然可以将参数设置为可选:
@app.get("/items/")
async def get_item(item_id: Annotated[str | None, Query(max_length=10, min_length=3)]=None):
if item_id:
return {"item": item_id}
return "items"
另外,还可以使用正则表达式来限定查询参数的格式,比如:
from fastapi import FastAPI, Query
from typing import Annotated
app = FastAPI()
@app.get("/items/")
async def get_item(item_id: Annotated[str | None, Query(max_length=10, min_length=3, pattern=r'\w+\W+\w+')]=None):
if item_id:
return {"item": item_id}
return "items"
127.0.0.1:8001/items/?item_id=11-11
有效127.0.0.1:8001/items/?item_id=1111
无效
参考
- https://fastapi.tiangolo.com
- https://asgi.readthedocs.io/en/latest/introduction.html
- https://www.starlette.io
- https://docs.pydantic.dev/latest/
- https://fastapi.tiangolo.com/reference/parameters/