FastAPI第二天
第一天讲了如何快速搭建api以及如何利用路由参数,今天就来丰富一下其他的基本功能
1.参数校验
不论是前端还是后端,都同时涉及到参数校验这个功能。前端可能只是进行一些简单的判断校验;但是如果有人恶意绕过网页,直接向后端路由发送请求,这个时候后端检验就显得尤为重要。因此,现在的Web框架也基本包含了参数校验功能。
1.1 查询参数校验
之前我们讲了查询参数,今天我们就要为查询参数添加一些额外的校验,比如长度限制、修改名称、正则限制……
为了添加校验 ,我们需要引入Query,可以先来看看Query里面大概包含了什么
除了上面说的,还有大于(等于)、小于(等于)以及是否废弃。
那最基本的例子就是限制查询参数的长度以及内容
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`的形式
假如校验失败,结果会怎么样呢
由此可见,FastAPI的错误提示还是非常友好的。只有当按照校验规则输入的时候才能显示对应内容。
我们使用Query来为查询参数添加校验时也可以使查询参数变成必需参数,即把Query(None)
用Query(...)
替换
1.2 路径参数校验和数值检验
路径参数的校验和查询参数基本一致,使用Path就可以设置校验内容,但是由于Path、Query都是Param的子类,因此源码中依然有别名设置这个属性
但是路径参数不像查询参数,它有固定的键名,那么一旦设置别名就会导致名称识别不到而报错。
例子也很简单
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 复制代码
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
当然,如果觉得对每一个请求体字段使用Field来写样例太麻烦,也可以直接在Body中添加,修改代码如下图
效果其实是一样的
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 复制代码
这样,在执行请求的时候,请求头中就会显示这一次请求所消耗的时间。
这里的call_next其实可以为任何名字,因为它只是一个函数名,调用着各种路径操作函数。从源码来看
这个装饰器最终还是app.add_middleware(xxx)的形式,并且包含的是一个函数也就是我们这里的add_header,继续深挖
这个基本的HTTP中间件本身有call_next方法,并且每一次请求的时候都会调用一次我们的计算时间函数。
更加常用的添加中间件的方式是app.add_middleware(xxx)其中xxx就是中间件。解决跨域请求也可以使用中间件来完成