@提示: 微信搜索【猿码记】回复 【fastapi】即可获取源码信息~
在上篇文章中Python框架篇(2):FastApi-参数接收和验证: https://mp.weixin.qq.com/s/J2_gJxJk2VLfMXgoH1l8Cw简单学习了一些基础且常用的模型,下面稍微在学点复杂点的模型和使用方法
@注意:对参数parameter
目录结构做了优化:
│ ├── types # 声明入参和出参对应的Pydantic模型
│ │ ├── __init__.py
│ │ ├── request # 入参模型
│ │ └── response # 出参模型
在app/types/request/demo_param.py
文件中,新增内容如下:
...
class StudentParam(BaseModel):
"""
学生信息
"""
name: constr(min_length=2, max_length=4) # 长度
age: conint(ge=18, le=30) # 整数范围:18 <= age <= 30
class_name: str # 班级名称
class ClassInfoParam(BaseModel):
"""
班级信息
"""
class_name: str # 班级名称
class_num: int # 班级人数
teacher_name: str # 老师名称
在app/router
下,新增demo_router.py
文件,内容如下:
...
@router.post("/query/pydantic/multipleParamReceive")
async def multipleParamReceive(student: request.StudentParam, classInfo: request.ClassInfoParam):
"""
请求体-多参数接收-演示
"""
return {
"msg": "请求体-多参数接收",
"result": {
"student": student,
"classInfo": classInfo,
}
}
在app/types/request/demo_param.py
文件中,新增内容如下:
...
class NestedParam(BaseModel):
"""嵌套模型"""
teacher_id: int # 老师id
teacher_name: str # 老师名称
class_list: List[ClassInfoParam] # 老师下班级列表
...
在app/router
下,新增demo_router.py
文件,内容如下:
...
@router.post("/query/pydantic/nestedModel")
async def nestedModelDemo(param: request.NestedParam):
"""
请求体-嵌套模型接收-演示
"""
return {
"msg": "嵌套模型接收使用-示例",
"result": {
"param": param,
}
}
在开发Api
和写Api
文档的过程中,经常会遇到以下场景:
className
,入参是 class_name
; def Field(
default: Any = Undefined, #设置参数默认值,场景2
*,
default_factory: Optional[NoArgAnyCallable] = None, #指定一个函数,该函数的返回值将被用作字段的默认值
alias: Optional[str] = None,# 字段别名,场景4
title: Optional[str] = None,
description: Optional[str] = None,# 字段说明,用于文档生成,,场景1
exclude: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny', Any]] = None,
include: Optional[Union['AbstractSetIntStr', 'MappingIntStrAny', Any]] = None,
const: Optional[bool] = None,
gt: Optional[float] = None, # 条件判断:大于
ge: Optional[float] = None, # 条件判断:等于
lt: Optional[float] = None, # 条件判断:小于
le: Optional[float] = None, # 条件判断:小于等于
multiple_of: Optional[float] = None, # 用于指定数值字段的值必须是某个特定值的倍数
allow_inf_nan: Optional[bool] = None,
max_digits: Optional[int] = None,
decimal_places: Optional[int] = None,
min_items: Optional[int] = None,# 用于验证列表或元组字段的元素个数不少于指定的最小值
max_items: Optional[int] = None,# 用于验证列表或元组字段的元素个数不大于指定的最大值
unique_items: Optional[bool] = None, # 设置true,则验证列表或元组字段的元素不能重复
min_length: Optional[int] = None,# 字符串字段的最小长度
max_length: Optional[int] = None,# 字符串字段的最大长度
allow_mutation: bool = True,
regex: Optional[str] = None, # 正则验证
discriminator: Optional[str] = None,
repr: bool = True,
**extra: Any,
) -> Any:
参数:
examples
,用来给出参数示例
在app/types/request/demo_param.py
文件中,新增内容如下:
class FieldParam(BaseModel):
"""
Field使用示例
"""
name: str = Field(default='', max_length=4, description="填写姓名", examples=["张三"])
age: int = Field(default='', gt=18, description="填写年龄,必须大于18", examples=[20])
phone: str = Field(default='', description="填写手机号", examples=["17600000000"], regex=r'^1\d{10}$')
likes: List[str] = Field(description="填写爱好", examples=[["篮球", "足球"]], min_items=2,
unique_items=True)
为了演示方便,上面示例都是直接返回一个字典dict
,来代替响应模型,正常情况下,会封装个通用模型,并通过方法调用,好处有以下几点:
{
"code":200,
"msg":"处理成功",
"data":...,
"additional":{
"time":"2023-12-04 19:00:23",
"trace_id":"cc1b12a5dfee26a7dcc29fe47dcfbde0"
}
}
新增文件app/types/response/http_resp.py
,内容如下:
from datetime import datetime
from typing import Any
from pydantic import BaseModel, Field
from app.utils import StringUtil
# ---------------------- 定义模型 ----------------------
class Additional(BaseModel):
"""额外信息"""
time: str
trace_id: str
class HttpResponse(BaseModel):
"""http统一响应"""
code: int = Field(default=200) # 响应码
msg: str = Field(default="处理成功") # 响应信息
data: Any | None # 具体数据
additional: Additional # 额外信息
在app/types/response/http_resp.py
文件中,新增内容如下:
def ResponseSuccess(resp: Any) -> HttpResponse:
"""成功响应"""
currentTime = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return HttpResponse(
data=resp,
additional=Additional(
time=currentTime,
trace_id=StringUtil.GenerateMd5(currentTime),
))
def ResponseFail(msg: str, code: int = -1) -> HttpResponse:
"""响应失败"""
currentTime = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return HttpResponse(
code=code,
msg=msg,
additional=Additional(
time=currentTime,
trace_id=StringUtil.GenerateMd5(currentTime),
))
在app/router
下,新增demo_router.py
文件,内容如下:
# 导入前,需要先在app/types/response/__init__.py,引入http_resp
from app.types import response
@router.post("/resp/demo", summary="响应模型示例")
async def respDemo(param: request.FieldParam) -> response.HttpResponse:
"""
响应模型示例-演示
"""
if "游戏" in param.likes:
return response.ResponseFail("禁止玩游戏~")
return response.ResponseSuccess(param)
如果想忽略响应模型中的默认值时,可以设置属性
response_model_exclude_unset=True
,这样没有实际值的字段,将不会返回,如下:
@router.post("/resp/demo", summary="响应模型示例",response_model_exclude_unset=True)
当我们有了json
后,可以直接通过这个网站:https://jsontopydantic.com/进行生成,省的我们挨个去写
本文由 mdnice 多平台发布