FastAPI第二天---参数校验

FastAPI第二天

第一天讲了如何快速搭建api以及如何利用路由参数,今天就来丰富一下其他的基本功能

1.参数校验

不论是前端还是后端,都同时涉及到参数校验这个功能。前端可能只是进行一些简单的判断校验;但是如果有人恶意绕过网页,直接向后端路由发送请求,这个时候后端检验就显得尤为重要。因此,现在的Web框架也基本包含了参数校验功能。

1.1 查询参数校验

之前我们讲了查询参数,今天我们就要为查询参数添加一些额外的校验,比如长度限制、修改名称、正则限制……

为了添加校验 ,我们需要引入Query,可以先来看看Query里面大概包含了什么

image-20220220124036034

除了上面说的,还有大于(等于)、小于(等于)以及是否废弃。

那最基本的例子就是限制查询参数的长度以及内容

from typing import Optional
from fastapi import FastAPI,Query

app=FastAPI()

@app.get("/test/")
async def test(q:Optional[str]=Query(None,min_length=6,max_length=10,regex="^shelgi.*$",description='开头必须为shelgi,并且字符串长度在6-10之间')):
    results="test"
    if q:
        results+=q
    return results

这个校验就是最少长度为6,最大长度为10,并且查询参数必须是``shelgixxx`的形式

image-20220220130537978

假如校验失败,结果会怎么样呢

image-20220220125442026

image-20220220125511068

由此可见,FastAPI的错误提示还是非常友好的。只有当按照校验规则输入的时候才能显示对应内容。

image-20220220125741038

我们使用Query来为查询参数添加校验时也可以使查询参数变成必需参数,即把Query(None)Query(...)替换

1.2 路径参数校验和数值检验

路径参数的校验和查询参数基本一致,使用Path就可以设置校验内容,但是由于Path、Query都是Param的子类,因此源码中依然有别名设置这个属性

image-20220220150307805

但是路径参数不像查询参数,它有固定的键名,那么一旦设置别名就会导致名称识别不到而报错。

例子也很简单

from typing import Optional
from fastapi import FastAPI, Path, Query

app = FastAPI()


@app.get("/test/{item_id}")
async def test(
        item_id: int = Path(..., description="用户的ID(1-100)之间", ge=1, le=100),
        q: Optional[str] = Query(None)
):
    results = {
    
    "item_id": item_id}
    if q:
        results.update({
    
    "q": q})
    return results

image-20220220151000401

2.请求体

这里就涉及到POST请求,向服务器发送数据。我们可以自定义请求体的字段内容,也可以利用Field为每个字段添加校验限制,而且可以将路径参数,查询参数和请求体结合起来,共同实现更加完整的请求功能。

# 请求体
from typing import Optional

from fastapi import FastAPI, Body, Path
from pydantic import BaseModel, Field

app = FastAPI()


class Item(BaseModel):
    name: str=Field(None,description="物品的名称",example="苹果")
    description: Optional[str] = Field(
        None, description="对物品的描述", max_length=300,example="这是用来吃的"
    )
    price: float = Field(..., gt=0, description="价格大于等于0",example=10)
    tax: Optional[float] = None


@app.put("/items/{item_id}")
async def update_item(
        item_id: int = Path(..., description="物品的ID(1-100)之间", ge=1, le=100),
        item: Item = Body(..., embed=True)
):
    results = {
    
    "item_id": item_id, "item": item}
    return results

image-20220220154953408

当然,如果觉得对每一个请求体字段使用Field来写样例太麻烦,也可以直接在Body中添加,修改代码如下图

image-20220220155607055

效果其实是一样的

3.中间件

中间件也是Web框架中常见的一部分,可以将一些常用的功能作为中间件随时调用。最简单的就是计时中间件,在上面的代码中添加一段

from fastapi import Request
@app.middleware("http")
async def add_header(request:Request,call_next):
    start=time.time()
    response=await call_next(request)
    cost=time.time()-start
    response.headers['Process-Time']=str(cost)
    return response

这样,在执行请求的时候,请求头中就会显示这一次请求所消耗的时间。

image-20220220161239660

这里的call_next其实可以为任何名字,因为它只是一个函数名,调用着各种路径操作函数。从源码来看

image-20220220162648888

这个装饰器最终还是app.add_middleware(xxx)的形式,并且包含的是一个函数也就是我们这里的add_header,继续深挖

image-20220220162828183

这个基本的HTTP中间件本身有call_next方法,并且每一次请求的时候都会调用一次我们的计算时间函数。

更加常用的添加中间件的方式是app.add_middleware(xxx)其中xxx就是中间件。解决跨域请求也可以使用中间件来完成

image-20220220170823281

猜你喜欢

转载自blog.csdn.net/shelgi/article/details/123033092