FastAPI-url参数: 路径参数校验&查询参数校验

为什么要参数校验

大家应该都听过一个笑话,一个程序员写好了咖啡厅程序。测试,点1杯咖啡,没问题。点0.1杯水,提示只能点整数杯,没问题。给客户用,客户点了个炒粉,咖啡厅炸了。

hhhh,这个笑话是想表达永远不要相信用户的输入。

那么我们在做Web服务,写程序的时候。对用户传来的url做参数校验是很有必要的。下面看看怎么做吧。

下面分为两个部分。

  • 路径参数校验
  • 查询参数校验

路径参数校验

使用Path为路径参数声明类型的校验和元数据(元素据指描述数据属性的信息, 比如数据的类型,取值范围)

import uvicorn
from typing import Annotated # 引入 Annotated
from fastapi import FastAPI, Path # 引入 Path
import asyncio

app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get")]
): # Annotated在参数列表中使用, 用于限制参数类型,声明元数据; Path限制数值范围 
    results = {"item_id": item_id}
    return results

if __name__ == '__main__':
    config = uvicorn.Config(app, host='127.0.0.1', port=8000)
    server = uvicorn.Server(config)
    asyncio.run(server.serve())

浏览器中输入 http://127.0.0.1:8000/items/5

会看到 {"item_id":5}

下面再看看Path能起到什么作用

这里Path里, ge=5, 指限制的范围是大于(greater than) 或 等于(equal) 5

import uvicorn
from typing import Annotated
from fastapi import FastAPI, Path
app = FastAPI()
@app.get("/items/{item_id}")
async def read_items(
    item_id: Annotated[int, Path(title="The ID of the item to get", ge=5)]
):
    results = {"item_id": item_id}
    return results

浏览器中输入 http://127.0.0.1:8000/items/6

会看到 {"item_id":6}

如果输入的值小于5, 会看到下面的内容

{
    "detail": [
        {
            "type": "greater_than_equal",
            "loc": [
                "path",
                "item_id"
            ],
            "msg": "Input should be greater than or equal to 5",
            "input": "3",
            "ctx": {
                "ge": 5
            }
        }
    ]
}

校验的类型也可以选择是float等

可选的声明数值校验:

gt:大于(greater tha n) ge:大于等于(greater than or equ al) lt:小于(less t han) le:小于等于(less than or equal)

查询参数校验

查询参数 q 的类型为 str,默认值为 None,因此它是可选的。


import uvicorn
from fastapi import FastAPI
app = FastAPI()
@app.get("/items/")
async def read_items(q: str | None = None):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

如果在浏览器中输入 http://127.0.0.1:8000/items/?q=test

会看到 {"items":[{"item_id":"Foo"},{"item_id":"Bar"}],"q":"test"}

如果在浏览器中输入 http://127.0.0.1:8000/items/

会看到 {"items":[{"item_id":"Foo"},{"item_id":"Bar"}]}

更多校验条件

  • max_length
  • min_length
  • 正则表达式

max_length

首先从 fastapi 导入 Query:

现在,将 Query 用作查询参数的默认值,并将它的 max_length 参数设置为 5

import uvicorn
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str | None = Query(default=None, max_length=5)):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

如果在浏览器中输入 http://127.0.0.1:8000/items/?q=testdata

会看到

{
    "detail": [
        {
            "type": "string_too_long",
            "loc": [
                "query",
                "q"
            ],
            "msg": "String should have at most 5 characters",
            "input": "testdata",
            "ctx": {
                "max_length": 5
            }
        }
    ]
}
min_length

添加 min_length 参数,限制查询参数的最小长度

import uvicorn
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str | None = Query(default=None, min_length=3, max_length=5)):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results
正则表达式

添加正则表达式,限制参数值必须匹配正则表达式


import uvicorn
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str | None = Query(default=None, min_length=3
, max_length=5, pattern="^test.?$")):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

正则表达式 "^test.?$" ,

^test 指以test开头, ^就是以什么开头。

.?指0个或1个任意字符

$ 指没有更多

因此 test,testa,testb都是匹配的, testabc是不匹配的

声明为必须参数

前面不是必须参数是因为使用 “str | None = Query()” 声明, 直接使用 “str = Query()” 声明, 那么这就是个必须参数

import uvicorn
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str = Query(min_length=3, max_length=5, pattern="^test.?$")):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

另一种方法, 将Query的默认值设置为 ... 


import uvicorn
from fastapi import FastAPI, Query
app = FastAPI()
@app.get("/items/")
async def read_items(q: str = Query(default=..., min_length=3)):
    results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]}
    if q:
        results.update({"q": q})
    return results

声明更多元素据

使用title和description 添加对数据的描述

Query(default=None, title="Query string", description="Query string for the items to search in the database", min_length=3)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值