查询参数模型
如果你有一组相关的查询参数,你可以创建一个Pydantic模型来声明它们。
这将允许您在多个地方重用模型,并一次声明所有参数的验证和元数据。😎
注:
自FastAPI 0.115.0版本起支持此功能。(当前2024.10.20日最新版本是0.115.2)🤓
使用Pydantic模型查询参数
在Pydantic模型中声明所需的查询参数,然后将参数声明为query:
from typing import Annotated, Literal
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class FilterParams(BaseModel):
limit: int = Field(100, gt=0, le=100)
offset: int = Field(0, ge=0)
order_by: Literal["created_at", "updated_at"] = "created_at"
tags: list[str] = []
@app.get("/items/")
async def read_items(filter_query: Annotated[FilterParams, Query()]):
return filter_query
这是python3.10以上版本的代码,对Annotated导入来自typing,而3.10以下如python3.9 的导入来自typing_extensions:
from typing_extensions import Annotated, Literal
python3.10以上的导入是:
from typing import Annotated, Literal
FastAPI将从请求中的查询参数中提取每个字段的数据,并为您提供您定义的Pydantic模型。
查看文档
您可以在/docs的文档界面中看到查询参数:
禁止额外查询参数
在某些特殊用例中(可能不是很常见),您可能希望限制要接收的查询参数。
您可以使用Pydantic的模型配置来禁止任何额外的字段:
from typing import Annotated, Literal
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class FilterParams(BaseModel):
model_config = {"extra": "forbid"}
limit: int = Field(100, gt=0, le=100)
offset: int = Field(0, ge=0)
order_by: Literal["created_at", "updated_at"] = "created_at"
tags: list[str] = []
@app.get("/items/")
async def read_items(filter_query: Annotated[FilterParams, Query()]):
return filter_query
如果客户端试图在查询参数中发送一些额外的数据,他们将收到错误响应。
例如,如果客户端试图发送一个值为plumbus的工具查询参数,就想:https://example.com/items/?limit=10&tool=plumbus
他们将收到一个错误响应,告诉他们不允许使用查询参数工具:
{
"detail": [
{
"type": "extra_forbidden",
"loc": ["query", "tool"],
"msg": "Extra inputs are not permitted",
"input": "plumbus"
}
]
}
摘要
您可以使用Pydantic模型在FastAPI中声明查询参数。😎
小贴士
剧透警告:您还可以使用Pydantic模型来声明Cookie和头文件,但您将在本教程稍后阅读相关内容。🤫
实践
查询参数
写文件query.py
from typing import Annotated, Literal
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class FilterParams(BaseModel):
limit: int = Field(100, gt=0, le=100)
offset: int = Field(0, ge=0)
order_by: Literal["created_at", "updated_at"] = "created_at"
tags: list[str] = []
@app.get("/items/")
async def read_items(filter_query: Annotated[FilterParams, Query()]):
return filter_query
启动服务器:
uvicorn query:app --reload
浏览链接:http://127.0.0.1:8000/items/?offset=2&tags=helloworld&limit=55
输出:
{"limit":55,"offset":2,"order_by":"created_at","tags":["helloworld"]}
浏览链接:http://127.0.0.1:8000/items/?offset=2&tags=helloworld&limit=55&test=1
输出: {"limit":55,"offset":2,"order_by":"created_at","tags":["helloworld"]}
禁止额外查询
写文件query.py
from typing import Annotated, Literal
from fastapi import FastAPI, Query
from pydantic import BaseModel, Field
app = FastAPI()
class FilterParams(BaseModel):
model_config = {"extra": "forbid"}
limit: int = Field(100, gt=0, le=100)
offset: int = Field(0, ge=0)
order_by: Literal["created_at", "updated_at"] = "created_at"
tags: list[str] = []
@app.get("/items/")
async def read_items(filter_query: Annotated[FilterParams, Query()]):
return filter_query
启动服务器:
uvicorn query:app --reload
浏览链接:http://127.0.0.1:8000/items/?offset=2&tags=helloworld&limit=55&test=1
输出:
{"detail":[{"type":"extra_forbidden","loc":["query","test"],"msg":"Extra inputs are not permitted","input":"1"}]}