提出问题
开发时,要对传入的数据做校验,如:
- 传入姓名,要校验长度,如:最小2个字符,最长20个字符
- 传入年龄,要校验最小值大于1岁,最大值小于120岁
例子
根据姓名查询学生,要求学生姓名必须是2-3个字符
from fastapi import FastAPI
app = FastAPI()
@app.get('/student/{name}')
async def get_student(name: str):
if len(name)<2:
return {
"msg":"姓名不能少于2个字符"
}
elif len(name)>3:
return {
"msg":"姓名不能多于3个字符"
}
if name == '李雷':
student = {
'name': '李雷',
'age': 21,
}
else:
student = {
'message': '没有此学号的学生',
}
return student
分析
每次需要写校验判断,太复杂
解决
使用 fastapi 的 Path() 参数校验
介绍
Path() 用于 路径参数(URL {xxx}),做校验、写接口文档。
对路径参数做:最小值、最大值、正则、描述、别名等校验。
提示:这种用法是 旧版用法,新项目不推荐,老项目还在大量使用
注意
Path 只作用于 路径参数,不能用于查询参数;查询参数用 Query()。
常用参数
第一个参数
是路径参数的 默认值,官方推荐必须写,无默认值写 ...(省略号用法详见 链接)
提示:不传第一个参数也可行,底层做了兼容处理,但旧版用法推荐传值
其他参数
如下表格:
| 参数 | 类型 | 作用 | 适用类型 | 备注 |
|---|---|---|---|---|
ge |
float 或 None |
大于等于(greater or equal) | int / float |
ge=1 → 值 ≥1 |
gt |
float 或 None |
大于(greater than) | int / float |
gt=1 → 值 >1 |
le |
float 或 None |
小于等于(less or equal) | int / float |
le=100 → 值 ≤100 |
lt |
float 或 None |
小于(less than) | int / float |
lt=100 → 值 <100 |
min_length |
int 或 None |
字符串最小长度 | str |
包含边界,min_length=2最少2个字符 |
max_length |
int 或 None |
字符串最大长度 | str |
包含边界,max_length=10最多10个字符 |
pattern |
str 或 None |
正则匹配表达式 | str |
原始正则字符串,例如 r"^A\d{4}$";不匹配返回422 |
title |
str 或 None |
OpenAPI文档参数标题 | 全部类型 | 仅接口文档显示,不参与校验 |
description |
str 或 None |
OpenAPI详细描述 | 全部类型 | 仅接口文档,不会改变报错提示 |
example |
Any |
单个示例值 | 全部类型 | 文档展示一个样例 |
examples |
dict或list 或 None |
多组示例 | 全部类型 | 可以传列表 [1,10];也可以传OpenAPI标准dict格式 |
deprecated |
bool 或 None |
标记参数废弃 | 全部类型 | deprecated=True,接口文档划横线提示废弃,不阻止请求 |
案例:重新上面的功能
from fastapi import FastAPI, Path
app = FastAPI()
@app.get('/student/{name}')
async def get_student(name: str=Path(...,min_length=2,max_length=3)):
if name == '李雷':
student = {
'name': '李雷',
'age': 21,
}
else:
student = {
'message': '没有此学号的学生',
}
return student
测试:长度过短
访问:http://127.0.0.1:8000/student/李,浏览器显示如下:
{
"detail": [
{
"type": "string_too_short",
"loc": [
"path",
"name"
],
"msg": "String should have at least 2 characters",
"input": "李",
"ctx": {
"min_length": 2
}
}
]
}
解释:
type:错误类型,string_too_short,即:字符串太短loc...path...name:表示路径参数name报错了msg:错误信息,翻译过来是:字符串至少是2个字符input:表示当前传入的参数是李ctx:表示该参数最小长度是2
测试:长度过长
访问:http://127.0.0.1:8000/student/lili,浏览器显示如下:
{
"detail": [
{
"type": "string_too_long",
"loc": [
"path",
"name"
],
"msg": "String should have at most 3 characters",
"input": "lili",
"ctx": {
"max_length": 3
}
}
]
}
解释:
type:错误类型,string_too_long,即:字符串太长loc...path...name:表示路径参数name报错了msg:错误信息,翻译过来是:字符串至多是3个字符input:表示当前传入的参数是lilictx:表示该参数最大长度是3
测试成功
访问:http://127.0.0.1:8000/student/李雷,浏览器显示如下:
{
"name": "李雷",
"age": 21
}
例子:校验数字
校验年龄,最小值大于10岁,最大值小于120岁
from fastapi import FastAPI,Path
app = FastAPI()
@app.get('/student/{age}')
async def update_student(age: int=Path(...,ge=10,le=120)):
print("age:", age)
return {'msg': '更新成功!'}
测试:年龄过小
访问:http://127.0.0.1:8000/student/9,浏览器显示如下:
{
"detail": [
{
"type": "greater_than_equal",
"loc": [
"path",
"age"
],
"msg": "Input should be greater than or equal to 10",
"input": "9",
"ctx": {
"ge": 10
}
}
]
}
解释:
type:错误类型,greater_than_equal,即:大于等于loc...path...age:表示路径参数age报错了msg:错误信息,翻译过来是:输入应该大于等于10input:表示当前传入的参数是9ctx:表示该参数应大于等于10
测试:年龄过大
访问:http://127.0.0.1:8000/student/121,浏览器显示如下:
{
"detail": [
{
"type": "less_than_equal",
"loc": [
"path",
"age"
],
"msg": "Input should be less than or equal to 120",
"input": "121",
"ctx": {
"le": 120
}
}
]
}
解释:
type:错误类型,less_than_equal,即:小于等于loc...path...age:表示路径参数age报错了msg:错误信息,翻译过来是:输入应该小于等于120input:表示当前传入的参数是121ctx:表示该参数应小于等于120