FastAPI -- 第二弹(响应模型、状态码、路由APIRouter、后台任务BackgroundTasks)
响应模型
添加响应模型
from typing import Anyfrom fastapi import FastAPI
from pydantic import BaseModel, EmailStrapp = FastAPI()class UserIn(BaseModel):username: strpassword: stremail: EmailStrfull_name: str | None = Noneclass UserOut(BaseModel):username: stremail: EmailStrfull_name: str | None = None# 通过 response_model 设置返回模型
@app.post("/user/", response_model=UserOut)
async def create_user(user: UserIn) -> Any:return user
模型的其他操作
继承 & 解包
from fastapi import FastAPI
from pydantic import BaseModel, EmailStrapp = FastAPI()# 定义一个 Base
# 包含公共属性,比如 id create_time update_time 等
class UserBase(BaseModel):username: stremail: EmailStrfull_name: str | None = None# 继承 Base
class UserIn(UserBase):password: str# 继承 Base
class UserOut(UserBase):pass# 继承 Base
class UserInDB(UserBase):hashed_password: strdef fake_password_hasher(raw_password: str):return "supersecret" + raw_passworddef fake_save_user(user_in: UserIn):hashed_password = fake_password_hasher(user_in.password)# 解包# user_in = UserIn(username="john", password="secret", email="john.doe@example.com")# **user_in.dict() ==> # username = user_dict["username"],# password = user_dict["password"],# email = user_dict["email"],# full_name = user_dict["full_name"], user_in_db = UserInDB(**user_in.dict(), hashed_password=hashed_password)print("User saved! ..not really")return user_in_db@app.post("/user/", response_model=UserOut)
async def create_user(user_in: UserIn):user_saved = fake_save_user(user_in)return user_saved
组合模型 (Union & dict)
union
union:组合多个模型,但返回值只能是一个模型的实例
from typing import Unionfrom fastapi import FastAPI
from pydantic import BaseModelapp = FastAPI()class BaseItem(BaseModel):description: strtype: strclass CarItem(BaseItem):type: str = "car"class PlaneItem(BaseItem):type: str = "plane"size: intitems = {"item1": {"description": "All my friends drive a low rider", "type": "car"},"item2": {"description": "Music is my aeroplane, it's my aeroplane","type": "plane","size": 5,},"item3": [{"description": "item3_1 Music is my aeroplane, it's my aeroplane","type": "plane","size": 5,},{"description": "item3_2 Music is my aeroplane, it's my aeroplane","type": "plane","size": 5,},]
}# Union[PlaneItem, CarItem, list[PlaneItem]],。。。。]
# 允许返回 Union 的多种类型中的 一种
@app.get("/items/{item_id}", response_model=Union[PlaneItem, CarItem,list[PlaneItem]])
async def read_item(item_id: str):return items[item_id]
dict
response_model=dict ,
response_model=dict[str, list] ,
response_model=list …dict 有点类似于 any, 但又比 any 更具体一些
比如 any 可以是 list 也可以是 dict, 但 dict 只能是 dict 不能是 list
比如 dict 可以是 dict[str, list], dict[int, list] 等,但 dict[str, list] 只能是 dict[str, list]
from fastapi import FastAPIapp = FastAPI()# 测试 Any
@app.get("/test_any/")
async def read_keyword_weights():# return {"foo": 2.3, "bar": 3.4}return [1, 2, 3]# 测试 dict
@app.get("/test_dict/", response_model=dict)
async def read_keyword_weights():return {"foo": 2.3, "bar": [1, 2, 3]}# 测试 dict[str, float]
@app.get("/test_dict_str_float/", response_model=dict[str, float])
async def read_keyword_weights():return {"foo": 2.3, "bar": 3.4}# return {"foo": 2.3, "bar": [1, 2, 3]}
响应状态码
from enum import IntEnum
from http import HTTPStatusfrom fastapi import FastAPI, statusapp = FastAPI()# 通过 http模块的 HTTPStatus 类,
# 我们可以很方便的使用一些常见的状态码,如下
@app.get("/items/http_status", status_code=HTTPStatus.OK)
def test_status_code():return "hallow world HTTPStatus"# 通过 fastapi 的 status 模块,
# 我们可以很方便的使用一些常见的状态码,如下
@app.get("/items/status", status_code=status.HTTP_201_CREATED)
def test_status_code():return "hallow world status"# 也可以直接使用数字
@app.get("/items/num", status_code=201)
def test_status_code():return "hallow world num"
顺便记一下,可以仿照 HTTPStatus 的写法,自定义状态码。
注意:自定义状态码是放到 响应体 里的,放到 status_code 后面有可能会报错哦
# 自定义的状态码
class MyHTTPStatus(IntEnum): def __new__(cls, value, phrase, description=''):obj = int.__new__(cls, value)obj._value_ = valueobj.phrase = phraseobj.description = descriptionreturn objCode200000 = 200000, 'OK', 'Request fulfilled, document follows'# client errorCode400000 = (400000, 'Bad Request','Bad request syntax or unsupported method')# 响应体示例
# {
# "code": 200000,
# "message": "OK",
# "data": {
# "name": "张三"
# }
# }
From表单
from fastapi import FastAPI, Formapp = FastAPI()# 和 Boday Query 类似,Form 也是从 fastapi 导入
# username: str = Form()
@app.post("/login/")
async def login(username: str = Form(), password: str = Form()):return {"username": username}
上传文件 (File, UploadFile)
from fastapi import FastAPI, File, UploadFileapp = FastAPI()@app.post("/files/")
async def create_file(file: bytes = File()):return {"file_size": len(file)}# 和前面的可选参数类似,如果 file 是可选的可以使用如下的方式声明
# file: UploadFile | None = None
# 多文件上传
# files: list[UploadFile]
@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):return {"filename": file.filename}
UploadFile 与 bytes 相比有更多优势:
- 使用 spooled 文件
- 存储在内存的文件超出最大上限时,FastAPI 会把文件存入磁盘
- 这种方式更适于处理图像、视频、二进制文件等大型文件,好处是不会占用所有内存
- 可获取上传文件的元数据
- 自带 file-like async 接口
- 暴露的 Python SpooledTemporaryFile 对象,可直接传递给其他预期「file-like」对象的库。
UploadFile
UploadFile 的属性
- filename:上传文件名字符串(str),例如, myimage.jpg;
- content_type:内容类型(MIME 类型 / 媒体类型)字符串(str),例如,image/jpeg;
- file: SpooledTemporaryFile( file-like 对象)。其实就是 Python文件,可直接传递给其他预期 file-like 对象的函数或支持库。
UploadFile 支持以下 async 方法
- write(data):把 data (str 或 bytes)写入文件;
- read(size):按指定数量的字节或字符(size (int))读取文件内容;
- seek(offset):移动至文件 offset (int)字节处的位置
- 例如,await myfile.seek(0) 移动到文件开头, 执行 await myfile.read() 后,需再次读取已读取内容时,这种方法特别好用;
- close():关闭文件
依赖项
声明依赖项
- 提高代码的复用性
from typing import Unionfrom fastapi import Depends, FastAPIapp = FastAPI()# 为查询接口设置一些公共参数
async def common_parameters(q: Union[str, None] = None, skip: int = 0, limit: int = 100
):return {"q": q, "skip": skip, "limit": limit}# 通过 Depends 声明依赖项
@app.get("/items/")
async def read_items(commons: dict = Depends(common_parameters)):return commons@app.get("/users/")
async def read_users(commons: dict = Depends(common_parameters)):return commons
APIRouter
相当于 Flask 的 Blueprints
目录结构
.
├── app # 「app」是一个 Python 包
│ ├── __init__.py # 这个文件使「app」成为一个 Python 包
│ ├── main.py # 「main」模块,例如 import app.main
│ ├── dependencies.py # 「dependencies」模块,例如 import app.dependencies
│ └── routers # 「routers」是一个「Python 子包」
│ │ ├── __init__.py # 使「routers」成为一个「Python 子包」
│ │ ├── items.py # 「items」子模块,例如 import app.routers.items
│ │ └── users.py # 「users」子模块,例如 import app.routers.users
│ └── internal # 「internal」是一个「Python 子包」
│ ├── __init__.py # 使「internal」成为一个「Python 子包」
│ └── admin.py # 「admin」子模块,例如 import app.internal.admin
app/dependencies.py
from fastapi import Header, HTTPExceptionasync def get_token_header(x_token: str = Header()):if x_token != "fake-super-secret-token":raise HTTPException(status_code=400, detail="X-Token header invalid")async def get_query_token(token: str):if token != "jessica":raise HTTPException(status_code=400, detail="No Jessica token provided")
app/routers/items.py
from fastapi import APIRouter, Depends, HTTPException# 可以使用相对路径进行导入操作
# 但个人不推荐这样操作
from ..dependencies import get_token_header# 定义 APIRouter(定义模块 / 定义蓝图)
router = APIRouter(prefix="/items",tags=["items"],dependencies=[Depends(get_token_header)],responses={404: {"description": "Not found"}},
)fake_items_db = {"plumbus": {"name": "Plumbus"}, "gun": {"name": "Portal Gun"}}# prefix + path
# api ==》 /items/
@router.get("/")
async def read_items():return fake_items_db# prefix + path
# api ==》 /items/{item_id}
@router.get("/{item_id}")
async def read_item(item_id: str):if item_id not in fake_items_db:raise HTTPException(status_code=404, detail="Item not found")return {"name": fake_items_db[item_id]["name"], "item_id": item_id}@router.put("/{item_id}",tags=["custom"],responses={403: {"description": "Operation forbidden"}},
)
async def update_item(item_id: str):if item_id != "plumbus":raise HTTPException(status_code=403, detail="You can only update the item: plumbus")return {"item_id": item_id, "name": "The great Plumbus"}
app/main.py
from fastapi import Depends, FastAPIfrom .dependencies import get_query_token, get_token_header
from .internal import admin# 导入模块路由
from .routers import items, usersapp = FastAPI(dependencies=[Depends(get_query_token)])# 为应用注册模块路由
app.include_router(users.router)
app.include_router(items.router)
app.include_router(admin.router,prefix="/admin",tags=["admin"],dependencies=[Depends(get_token_header)],responses={418: {"description": "I'm a teapot"}},
)@app.get("/")
async def root():return {"message": "Hello Bigger Applications!"}
后台任务 BackgroundTasks
from fastapi import BackgroundTasks, FastAPIapp = FastAPI()def write_notification(email: str, message=""):with open("log.txt", mode="w") as email_file:content = f"notification for {email}: {message}"email_file.write(content)@app.post("/send-notification/{email}")
async def send_notification(email: str, background_tasks: BackgroundTasks):# 直接在视图函数中添加一个参数 background_tasks: BackgroundTasks# 然后通过 background_tasks.add_task ,添加为后台任务# 并没有看到 background_tasks 创建,# 应该是 FastAPI 会创建一个 BackgroundTasks 类型的对象并作为该参数传入background_tasks.add_task(write_notification, email, message="some notification")return {"message": "Notification sent in the background"}
到此结 DragonFangQy 2024.07.13
相关文章:
FastAPI -- 第二弹(响应模型、状态码、路由APIRouter、后台任务BackgroundTasks)
响应模型 添加响应模型 from typing import Anyfrom fastapi import FastAPI from pydantic import BaseModel, EmailStrapp FastAPI()class UserIn(BaseModel):username: strpassword: stremail: EmailStrfull_name: str | None Noneclass UserOut(BaseModel):username: s…...

案例 | 人大金仓助力山西政务服务核心业务系统实现全栈国产化升级改造
近日,人大金仓支撑山西涉企政策服务平台、政务服务热线联动平台、政务网、办件中心等近30个政务核心系统完成全栈国产化升级改造,推进全省通办、跨省通办、综合业务受理、智能审批、一件事一次办等业务的数字化办结进程,为我国数字政务服务提…...

如何用python写接口
如何用python写接口?具体步骤如下: 1、实例化server 2、装饰器下面的函数变为一个接口 3、启动服务 开发工具和流程: python库:flask 》实例化server:server flask.Flask(__name__) 》server.route(/index,met…...

轻量级可扩展易航网址引导系统源码V2.45
由于现在网站行业的不稳定,导致很地址频繁更换,不仅是网站,联系QQ,加群链接等需要更换时,好不容易发展的客户会因为找不到您新的网站地址而流失,有了引导页以后就可以安心地宣传无需担心客户丢失的问题。 …...

解决ESLint和Prettier冲突的问题
在配置了ESLint的项目中使用Prettier进行格式化可能会出现冲突,不如Prettier配置了使用双引号,ESLint配置了单引号,当然可以一个一个改成一样的配置,但是比较麻烦。我发现可以直接使用ESLint的规则进行格式化。在VSCode配置过程如…...

C判断一个点在三角形上
背景 鼠标操作时,经常要判断是否命中显示控件,特开发此算法快速判断。 原理 三角形三等分点定理是指在任意三角形ABC中,可以找到三个点D、E和F,使得线段AD、BE和CF均等分三角形ABC。 这意味着三个等分点分别位于三个边界上&…...

物业系统自主研发接口测试框架
1、自主研发框架整体设计 1.1、什么是测试框架? 在了解什么是自动化测试框架之前,先了解一下什么叫框架?框架是整个或部分系统的可重用设计,表现为一组抽象构件及构件实例间交互的方法;另一种定义认为,框架是可被应用开发者定制的应用骨架…...

手机和电脑通过TCP传输
一.工具 手机端:网络调试精灵 电脑端:野火网络调试助手 在开始通信之前,千万要查看一下电脑的防火墙是否关闭,否则可能会无法通信 在开始通信之前,千万要查看一下电脑的防火墙是否关闭,否则可能会无法通信…...
Git 在commit后,撤销commit
1. 撤销已经add,但是没有commit的问题 git reset HEAD 2. 撤销已经commit,但是没有push到远端的文件(仅撤销commit 保留add操作) 撤销上一次的提交 git reset --soft HEAD^windows 系统使用提示 more,需要多加一个…...

多模态大模型 - MM1
1. 摘要 本文主要通过分析模型结构和数据选择讨论如何构建一个好的多模态大模型(MLLM),并同时提出了MM1模型,包括30B dense版本和64B的MoE版本。 具体贡献: 模型层面:影响效果的重要性排序为:…...
FPGA设计之跨时钟域(CDC)设计篇(2)----如何科学地设计复位信号?
1、复位是干嘛的? 时钟信号和复位信号应该是一个数字系统最重要和最常用的两个信号了。时钟的重要性大家都懂,没有时钟整个系统就无法同步,自然也就谈不上运行了。那么复位(reset)到底是干嘛的? 所有的数字系统在上电的时候都会进行复位,这样才能确保该系统的初始运行状…...
GPS北斗标准时钟同步服务器结构是什么?安徽京准
GPS北斗标准时钟同步服务器结构是什么?安徽京准 GPS北斗标准时钟同步服务器结构是什么?安徽京准 电厂时钟同步系统组成及配置 随着计算机和网络通信技术的飞速发展,火电厂热工自动化系统数字化、网络化的时代已经到来。一方面它为控制和信息系…...

9.5 栅格图层符号化多波段彩色渲染
文章目录 前言多波段彩色渲染QGis设置为多波段彩色二次开发代码实现多波段彩色 总结 前言 介绍栅格图层数据渲染之多波段彩色渲染说明:文章中的示例代码均来自开源项目qgis_cpp_api_apps 多波段彩色渲染 以“3420C_2010_327_RGB_LATLNG.tif”数据为例,…...

力扣第九题
回文数 提示: 给你一个整数 x ,如果 x 是一个回文整数,返回 true ;否则,返回 false 。 回文数是指正序(从左向右)和倒序(从右向左)读都是一样的整数。 代码展示&#…...

鞭炮插画:成都亚恒丰创教育科技有限公司
鞭炮插画:年味里的绚烂记忆 在岁末年初的温柔时光里,总有一抹色彩,能瞬间唤醒沉睡的年味——那便是鞭炮插画中跃动的红与金,成都亚恒丰创教育科技有限公司 它们不仅仅是纸与墨的交织,更是情感与记忆的桥梁,…...

python 循环
循环 while语句 for语句 循环控制语句 break 立即退出循环。 continue 跳过当前循环的剩余部分,并开始下一次迭代。 else for 和 while 循环都可以有一个可选的 else 子句,当循环正常结束时执行。 嵌套 占位符pass pass 是一个空操作语句。当你需要在代…...

映美精黑白相机IFrameQueueBuffer转halcon的HObject
映美精黑白相机,用wpfhalcon开发取图 1.到官网下载,开发包 1sdk 2c开发例子 3c#开发例子 引入TIS.Imaging.ICImagingControl35.dll 3.ICImagingControl使用这个类控制相机 /// <summary> /// 相机控制 /// </summary> public ICImagingC…...

Linux的load(负载)
负载(load)是Linux机器的一个重要指标,直观了反应了机器当前的状态。 在Linux系统中,系统负载是对当前CPU工作量的度量,被定义为特定时间间隔内运行队列中的平均线程数。 Linux的负载高,主要是由于CPU使用、内存使用、10消…...

杜比全景声——空间音频技术
什么是杜比?是否是标清、高清、超清之上的更清晰的格式?杜比全景声 和传统多声道立体声的差别?杜比全景声音频的渲染方式?车载平台上杜比技术的应用? 杜比技术的起源 杜比实验室(Dolby Laboratories&…...

C 语言指针进阶
1.0 指针的定义 指针是内存中一个最小单元的编号(内存单元的编号称之为地址【地址就是指针指针就是地址】)指针通常是用来存放内存地址的一个变量。本质上指针就是地址:口语上说的指针起始是指针变量,指针变量就是一个变量&#…...

eNSP-Cloud(实现本地电脑与eNSP内设备之间通信)
说明: 想象一下,你正在用eNSP搭建一个虚拟的网络世界,里面有虚拟的路由器、交换机、电脑(PC)等等。这些设备都在你的电脑里面“运行”,它们之间可以互相通信,就像一个封闭的小王国。 但是&#…...
synchronized 学习
学习源: https://www.bilibili.com/video/BV1aJ411V763?spm_id_from333.788.videopod.episodes&vd_source32e1c41a9370911ab06d12fbc36c4ebc 1.应用场景 不超卖,也要考虑性能问题(场景) 2.常见面试问题: sync出…...

K8S认证|CKS题库+答案| 11. AppArmor
目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作: 1)、切换集群 2)、切换节点 3)、切换到 apparmor 的目录 4)、执行 apparmor 策略模块 5)、修改 pod 文件 6)、…...

家政维修平台实战20:权限设计
目录 1 获取工人信息2 搭建工人入口3 权限判断总结 目前我们已经搭建好了基础的用户体系,主要是分成几个表,用户表我们是记录用户的基础信息,包括手机、昵称、头像。而工人和员工各有各的表。那么就有一个问题,不同的角色…...

高等数学(下)题型笔记(八)空间解析几何与向量代数
目录 0 前言 1 向量的点乘 1.1 基本公式 1.2 例题 2 向量的叉乘 2.1 基础知识 2.2 例题 3 空间平面方程 3.1 基础知识 3.2 例题 4 空间直线方程 4.1 基础知识 4.2 例题 5 旋转曲面及其方程 5.1 基础知识 5.2 例题 6 空间曲面的法线与切平面 6.1 基础知识 6.2…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...

OPENCV形态学基础之二腐蚀
一.腐蚀的原理 (图1) 数学表达式:dst(x,y) erode(src(x,y)) min(x,y)src(xx,yy) 腐蚀也是图像形态学的基本功能之一,腐蚀跟膨胀属于反向操作,膨胀是把图像图像变大,而腐蚀就是把图像变小。腐蚀后的图像变小变暗淡。 腐蚀…...
HybridVLA——让单一LLM同时具备扩散和自回归动作预测能力:训练时既扩散也回归,但推理时则扩散
前言 如上一篇文章《dexcap升级版之DexWild》中的前言部分所说,在叠衣服的过程中,我会带着团队对比各种模型、方法、策略,毕竟针对各个场景始终寻找更优的解决方案,是我个人和我司「七月在线」的职责之一 且个人认为,…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...