@提示: 如果想获取文章中具体的代码信息,可在微信搜索【猿码记】回复 【fastapi】即可。
1.参数接收
1.1 路径参数(不推荐)
1.代码清单
在app/router
下,新增demo_router.py
文件,内容如下:
from fastapi import APIRouter
router = APIRouter( prefix="/demo", tags=["演示接口"] )
@router.get("/path/{order_id}") async def pathParamReceive(order_id: int): """ 路径参数接收演示 """ return { "接受结果": order_id, }
|
@注意:当我们定义参数类型时,FastAPI 接受参数时,会自动进行”解析”,如果类型不一致,则会报错。
2.请求验证
➜ curl http://127.0.0.1:8000/demo/path/12222 {"接受结果":12222}
➜ curl http://127.0.0.1:8000/demo/path/hello {"detail":[{"loc":["path","order_id"],"msg":"value is not a valid integer","type":"type_error.integer"}]}
➜ curl http://127.0.0.1:8000/demo/path/ {"detail":"Not Found"}
|
3.顺序大坑
假如我们定义两个接口,带路径参数的:/path/{order_id}
和不带路径参数的:/path/test
,可能会因为顺序问题,导致我们无法正常访问/path/test
,例如路由注册时代码如下:
... @router.get("/path/{order_id}") async def pathParamReceive(order_id: int): """ 路径参数接收-演示-带路径参数 """ return { "接受结果": order_id, }
@router.get("/path/test") async def pathParamReceive2(): """ 路径参数接收-演示-不带路径参数 """ return { "msg": "hello", }
|
然后进行访问:
➜ curl http://127.0.0.1:8000/demo/path/99999 {"接受结果":99999}
➜ curl http://127.0.0.1:8000/demo/path/test {"detail":[{"loc":["path","order_id"],"msg":"value is not a valid integer","type":"type_error.integer"}]}
|
通过替换两个函数位置,就可以正常访问了, 感觉比较奇葩,不推荐使用,只做了解即可。更多使用方法可见官方文档: https://fastapi.tiangolo.com/zh/tutorial/path-params/
1.2 查询参数
1.代码清单
在app/router
下,新增demo_router.py
文件,内容如下:
from typing import Union ... @router.get("/query/receive") @router.get("/query/receive") async def queryParamReceive(username: str, sex: str = '男', city: Union[str, None] = None): """ 查询参数接受-演示 """ return { "msg": "查询参数接收", "result": { "username": username, "sex": sex, "city": city, } } ...
|
2.参数约束
username: str
: 代表参数username
为必填字段;
sex: str = '男'
: 代表参数sex
为选填字段,并且有默认值男
;
city: Union[str, None] = None
: 代表参数city
为选填字段,并无默认值; Union
是 typing
模块中的一个泛型类,用于表示多个类型中的一个;
@注意: 当参数有默认值时,顺序一定要放在没有默认值参数后面,否则会提示语法错误:SyntaxError: non-default argument follows default argument
3.请求验证
1.3 请求体(推荐)
使用请求体接受参数,一般分为两个步骤:
- 第一步: 使用
Pydantic
模型声明一个请求体(其实就是class
);
- 第二步: 路由函数的参数绑定上这个模型;
@注意:工作中比较常用的参数接收方式,推荐使用~
1.定义模型
文件位置: app/parameter/demo_param.py
from typing import Union
from pydantic import BaseModel
class DemoParam(BaseModel): """ 请求体参数对应的模型 """ user_name: str age: int city: Union[str, None]
|
2.优化导入
文件位置: app/parameter/__init__.py
from app.parameter.demo_param import DemoParam
|
3.使用
文件位置: app/router/demo_router.py
from app.parameter import DemoParam
router = APIRouter( prefix="/demo", tags=["演示接口"] )
@router.post("/query/receive") async def bodyReceive(body: DemoParam): """ 请求体参数接受-演示 """ return { "msg": "请求体参数接受", "result": { "body": body, } }
|
4.验证
curl -X 'POST' \ 'http://127.0.0.1:8000/demo/query/body/receive' \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "age": 99, "city": "北京" }'
{"detail":[{"loc":["body","user_name"],"msg":"field required","type":"value_error.missing"}]}
➜ curl -X 'POST' \ 'http://127.0.0.1:8000/demo/query/body/receive' \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "user_name": "娃哈哈", "age": 99, "city": "北京" }' {"msg":"请求体参数接受","result":{"body":{"user_name":"娃哈哈","age":99,"city":"北京"}}}
➜ curl -X 'POST' \ 'http://127.0.0.1:8000/demo/query/body/receive' \ -H 'accept: application/json' \ -H 'Content-Type: application/json' \ -d '{ "user_name": "", "age": 99, "city": "北京" }' {"msg":"请求体参数接受","result":{"body":{"user_name":"","age":99,"city":"北京"}}}
|
2.参数验证
在Python
中推荐使用成熟的第三方库进行数据验证,这样不仅可以少写一些if .. elif..
,还能让代码的可读性更强;
2.1 Pydantic介绍
Pydantic
是一个 Python
库,用于数据验证和设置,特别是用于验证数据模型。它通过声明性的方式定义数据模型,并提供了强大的数据验证和转换功能。Pydantic
最初是为 FastAPI
框架设计的,但它也可以在其他 Python
项目中独立使用。
@注意: 文中使用的pydantic
版本为: 1.10.11
, 貌似不同的版本,可能会存在差异;具体可参见官方文档: https://docs.pydantic.dev/latest/
使用Pydantic
的本质,其实就是如何编写对应的数据验证规则,下面列举一些常用的规则:
2.2 常用验证
下面列举一些常用的验证规则:
- 基本数据类型:
int
, float
, str
, bool
;
- 可选参数:
Optional[type]
表示可选参数,Union[x, None]
也可以表示可选;
- 整数范围: 结合
conint
函数判断数字范围 ,如age: conint(ge=18, le=30)
; ge:大于等于、gt:大于、le:小于等于、lt:小于
- 字符长度: 结合
constr
函数判断字符长度,如: constr(min_length=6, max_length=10)
;
- 正则表达式: 使用
constr
函数中的参数regex
,可以用于进行正则表达式验证;
- 枚举验证: 使用
Enum
定义枚举类,验证。
- 列表类型: 使用
List[type]
来限制列表值的类型,并尝试把参数转成对应的类型。
- 字典类型:
Dict[key_type, value_type]
来限制字典key
和val
类型,并尝试把参数转成对应的类型。
from enum import Enum from typing import Union, Optional, List, Dict
from pydantic import BaseModel, constr, conint
class GenderEnum(str, Enum): """ 性别枚举 """ male = "男" female = "女"
class PydanticVerifyParam(BaseModel): """ 用来学习使用pydantic模型验证 """ user_name: str age: conint(ge=18, le=30) password: constr(min_length=6, max_length=10) phone: constr(regex=r'^1\d{10}$') address: Optional[str] = None sex: GenderEnum likes: List[str] scores: Dict[str, float]
|
@注意:上面列举的都是基本使用,实际中可以组合进行多项组合使用,如items: List[constr(min_length=1, max_length=3)]
: 限制列表中的每个字符串长度的范围
2.3 自定义验证
@validator
装饰器用于定义自定义验证函数,具体是如下:
from pydantic import BaseModel, constr, conint, validator ... class PydanticVerifyParam(BaseModel): """ 用来学习使用pydantic模型验证 """ user_name: str ... @validator("user_name") def validateUsername(cls, value: str): """ 自定义验证函数 """ if value.find("傻") > -1: raise ValueError("user_name不能包含敏感词") return value
|
验证结果:
{ "detail": [ { "loc": [ "body", "user_name" ], "msg": "user_name不能包含敏感词", "type": "value_error" } ] }
|
2.4 其他验证
EmailStr
: 用于验证字符串是否是有效的电子邮件地址。
IPvAnyAddress
: 用于验证字符串是否是有效的 IPv4 或 IPv6 地址。
StrictBool
: 用于验证字符串是否是严格的布尔值(true
或 false
)。
AnyHttpUrl
: 用于验证字符串是否是有效的 URL
,包括以 http
或 https
开头的 URL
。
更多验证方式可查看文档: https://docs.pydantic.dev/latest/concepts/validators/