三周精通FastAPI:7 查询参数模型

查询参数模型



如果你有一组相关的查询参数,你可以创建一个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"}]}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值