fastapi 请求文件 / 表单 / 处理错误 / 路径操作配置 / jsonable_encoder
文章目录
- 1. File 参数
- 2. 多文件上传
- 3. 请求表单与文件
- 4. 处理错误
- 5. 自定义响应头
- 6. 自定义异常处理器
- 7. 覆盖默认异常处理器
- 8. 使用 RequestValidationError 的请求体
- 9. 复用 FastAPI 异常处理器
- 10. 路径操作参数配置
- 10.1 status_code,tags
- 10.2 summary,description
- 10.3 response description
- 10.4 deprecated 废除
- 11. jsonable_encoder() 转换
learn from https://fastapi.tiangolo.com/zh/tutorial/request-files/
1. File 参数
from fastapi import FastAPI, Form, File, UploadFile
app = FastAPI()@app.post("/files/")
async def create_file(file: bytes = File(...)):return {"file_size": len(file)}@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):contents = await file.read()return {"filename": file.filename}
bytes
形式, 文件的所有内容都存储在内存里,适用于小型文件- 很多情况下,
UploadFile
更好用
1.存储在内存里的文件超出上限,FastAPI 会将其存入磁盘,大型文件不会用尽所有内存
2.可获取上传文件的元数据
3.自带 file-like async 接口
在 async
路径操作函数 内,要用以下方式读取文件内容:
contents = await myfile.read()
在普通 def
路径操作函数 内,则可以直接访问 UploadFile.file
contents = myfile.file.read()
2. 多文件上传
List[bytes], List[UploadFile]
from fastapi import FastAPI, Form, File, UploadFile
from fastapi.responses import HTMLResponse
from typing import List
app = FastAPI()@app.post("/files/")
async def create_files(files: List[bytes] = File(...)):return {"file_sizes": [len(file) for file in files]}@app.post("/uploadfiles/")
async def create_upload_files(files: List[UploadFile] = File(...)):return {"filenames": [file.filename for file in files]}@app.get("/")
async def main():content = """
<body>
<form action="/files/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
</body>"""return HTMLResponse(content=content)
3. 请求表单与文件
- FastAPI 支持同时使用 File 和 Form 定义文件和表单字段
@app.post("/f/")
async def create_file(file1: bytes = File(...),file2: UploadFile = UploadFile(...),token: str = Form(...)
):return {"file_size": len(file1),"token" : token,"file_content_type" : file2.content_type}
- 可在一个路径操作中声明
多个 File
与Form
参数,但不能同时声明要接收JSON 的 Body
字段。因为此时请求体的编码为multipart/form-data
,不是application/json
4. 处理错误
- raise
HTTPException()
from fastapi import FastAPI, HTTPException
app = FastAPI()
items = {"foo" : "The Foo items"}@app.get("/items/{item_id}")
async def read_item(item_id: str):if item_id not in items:raise HTTPException(status_code=404, detail="item not found!")return {"item" : items[item_id]}
- 触发 HTTPException 时,可以用参数 detail 传递任何能转换为 JSON 的值,不仅限于
str
。还支持传递dict、list
等数据结构
INFO: Started server process [12136]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: 127.0.0.1:3229 - "GET /items/foo HTTP/1.1" 200 OK
INFO: 127.0.0.1:3240 - "GET /items/bar HTTP/1.1" 404 Not Found
- 使用 dict 形式的 detail 参数也可以,只要可以被转为 JSON 即可
HTTPException(status_code=404, detail={"msg":"item not found!", "name":["michael","ming"]})
5. 自定义响应头
HTTPException(headers=xxx)
@app.get("/items-header/{item_id}")
async def read_item_header(item_id: str):if item_id not in items:raise HTTPException(status_code=404,detail="Item not found",headers={"X-Error": "There goes my error!!!"},)return {"item": items[item_id]}
6. 自定义异常处理器
- 自定义异常类
- 编写 handler
@app.exception_handler(要处理的异常类)
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponseclass MichaelException(Exception):def __init__(self, name: str):self.name = nameapp = FastAPI()@app.exception_handler(MichaelException)
async def michael_exception_handler(request: Request, exec: MichaelException):return JSONResponse(status_code=408,content = {"msg": "哦,{}出错了".format(exec.name)})@app.get("/test/{name}")
async def test(name: str):if name == "yoyo":raise MichaelException(name)return {"test_name" : name}
7. 覆盖默认异常处理器
from fastapi import FastAPI, HTTPException
from fastapi.exceptions import RequestValidationError
from fastapi.responses import PlainTextResponseapp = FastAPI()
@app.get("/items/{item_id}")
async def read_item(item_id: int):if item_id == 3:raise HTTPException(status_code=418, detail="3 is not a good number")return {"item_id" : item_id}
- 更改
RequestValidationError
错误的处理 handler
from fastapi import FastAPI, HTTPException
from fastapi.exceptions import RequestValidationError
from fastapi.responses import PlainTextResponseapp = FastAPI()@app.exception_handler(RequestValidationError)
async def valid_excep_handler(req, exec):return PlainTextResponse(str(exec), status_code=400)@app.get("/items/{item_id}")
async def read_item(item_id: int):if item_id == 3:raise HTTPException(status_code=418, detail="3 is not a good number")return {"item_id" : item_id}
- 同样的,处理
HTTPException
的 handler,自定义处理
from starlette.exceptions import HTTPException as StarletteHTTPException
# 跟 fastapi 的 HTTPException 一样
@app.exception_handler(StarletteHTTPException)
async def http_exception_handler(req, exc):return PlainTextResponse(str(exc.detail), status_code=exc.status_code)
or
@app.exception_handler(HTTPException)
async def http_exception_handler(req, exc):return PlainTextResponse(str(exc.detail), status_code=exc.status_code)
8. 使用 RequestValidationError 的请求体
RequestValidationError
包含其接收到的 无效数据请求的 body 。可以用这个请求体生成日志、调试错误,并返回给用户
from fastapi import FastAPI, Request, status
from fastapi.encoders import jsonable_encoder
from fastapi.exceptions import RequestValidationError
from fastapi.responses import JSONResponse
from pydantic import BaseModelapp = FastAPI()@app.exception_handler(RequestValidationError)
async def valid_exception_handler(req: Request, exc: RequestValidationError):return JSONResponse(status_code=status.HTTP_422_UNPROCESSABLE_ENTITY,content=jsonable_encoder({"detail": exc.errors(), "body": exc.body}),)class Item(BaseModel):title: strsize: int@app.post("/items/")
async def create_item(item: Item):return item
输入 非整数的 size ,得到报错 {"detail": exc.errors(), "body": exc.body}
9. 复用 FastAPI 异常处理器
- 在自定义处理完异常之后,还可以继续使用 默认的异常处理器
from fastapi import FastAPI, HTTPException
from fastapi.exception_handlers import http_exception_handler, request_validation_exception_handler
from fastapi.exceptions import RequestValidationError
from starlette.exceptions import HTTPException as StarletteHTTPExceptionapp = FastAPI()@app.exception_handler(StarletteHTTPException) # 自定义处理异常
async def custom_http_exception_handler(req, exc):print(f"OMG! An HTTP error!: {repr(exc)}")return await http_exception_handler(req, exc) # 再调用自带的异常处理器@app.exception_handler(RequestValidationError)
async def validation_exception_handler(req, exc):print(f"OMG! The client sent invalid data!: {exc}")return await request_validation_exception_handler(req, exc)@app.get("/items/{item_id}")
async def read_item(item_id: int):if item_id == 3:raise HTTPException(status_code=418, detail="Nope! I don't like 3.")return {"item_id": item_id}
INFO: 127.0.0.1:9594 - "GET /items/abc HTTP/1.1" 422 Unprocessable Entity
OMG! The client sent invalid data!: 1 validation error for Request
path -> item_idvalue is not a valid integer (type=type_error.integer)
INFO: 127.0.0.1:8106 - "GET /items/abc HTTP/1.1" 422 Unprocessable Entity
INFO: 127.0.0.1:10417 - "GET /items/1 HTTP/1.1" 200 OK
OMG! An HTTP error!: HTTPException(status_code=418, detail="Nope! I don't like 3.")
INFO: 127.0.0.1:10417 - "GET /items/3 HTTP/1.1" 418
10. 路径操作参数配置
10.1 status_code,tags
tags = [字符串]
,将反映到 文档中
from typing import Optional, Setfrom fastapi import FastAPI
from pydantic import BaseModelapp = FastAPI()class Item(BaseModel):name: strdescription: Optional[str] = Noneprice: floattax: Optional[float] = Nonetags: Set[str] = []@app.post("/items/", response_model=Item, tags=["items, ming"], status_code=201)
async def create_item(item: Item):return item@app.get("/items/", tags=["items"])
async def read_items():return [{"name": "Foo", "price": 42}]@app.get("/users/", tags=["michael"])
async def read_users():return [{"username": "johndoe"}]
10.2 summary,description
@app.post("/items/", response_model=Item, tags=["items, ming"], status_code=201,summary="创建item",description="描述item的一些信息")
async def create_item(item: Item):return item
description
也可以由 多行注释直接生成,支持 MD 格式
@app.post("/items/", response_model=Item, tags=["items, ming"], status_code=201,summary="创建item",)
async def create_item(item: Item):'''多行注释 --> description- **name**: each item must have a name- **description**: a long description- **price**: required- **tax**: if the item doesn't have tax, you can omit this- **tags**: a set of unique tag strings for this item'''return item
10.3 response description
response_description
参数
@app.post("/items/", response_model=Item, tags=["items, ming"], status_code=201,summary="创建item",response_description="响应的描述")
async def create_item(item: Item):'''多行注释 --> description,支持 MD 格式## 1. 标题- **name**: each item must have a name- **description**: a long description- **price**: required- **tax**: if the item doesn't have tax, you can omit this- **tags**: a set of unique tag strings for this item'''return item
10.4 deprecated 废除
deprecated
@app.get("/users/", tags=["michael"], deprecated=True)
async def read_users():return [{"username": "johndoe"}]
11. jsonable_encoder() 转换
jsonable_encoder()
将pydantic
模型等数据结构 转换为 与json
兼容的格式(dict, list
等)
from datetime import datetime
from typing import Optionalfrom fastapi import FastAPI
from fastapi.encoders import jsonable_encoder
from pydantic import BaseModelfake_db = {}class Item(BaseModel):title: strtimestamp: datetimedescription: Optional[str] = Noneapp = FastAPI()@app.put("/items/{id}")
def update_item(id: str, item: Item):json_data = jsonable_encoder(item)fake_db[id] = json_datareturn fake_db
这个例子把 Pydantic model
转换为 dict
, 把 datetime
转换为 str
fastapi 请求文件 / 表单 / 处理错误 / 路径操作配置 / jsonable_encoder相关推荐
- html中只能上传文件word,HTML文件表单,接受Word文档(HTML file form, accept Word documents)...
HTML文件表单,接受Word文档(HTML file form, accept Word documents) 我在这里遇到了一个奇怪的问题. (不管怎样,或者我只是忽略了一些非常简单的东西.) 我 ...
- angularjs 表单校验指令_angular4.0的模板式表单、响应式表单及其错误提示
模板式表单 NgForm.NgModel.NgModelGroup是FormModule里的内容,NgForm会自动拦截标准的表单处理事件(eg.提交),angular用ngSubmit代替标准的表单 ...
- ios php 表单提交图片上传,axios发送post请求提交图片表单步骤详解
这次给大家带来axios发送post请求提交图片表单步骤详解,axios发送post请求提交图片表单的注意事项有哪些,下面就是实战案例,一起来看一下. DOME 接口const userUploadA ...
- js操作元素:改变元素内容有两种方式: interText 和 innerHTML的区别, 常用的元素的属性操作, 仿电脑系统时间问好 ,表单元素的属性操作 ,案例:仿京东显示隐藏密码 ,样式属性操作
文章目录 操作元素 改变元素内容有两种方式: interText 和 innerHTML的区别 常用的元素的属性操作 案例:仿电脑系统时间问好 表单元素的属性操作 案例:仿京东显示隐藏密码 样式属性操 ...
- 【JavaScript-事件②】表单元素的属性操作,密码显示隐藏的实现
目录 前言 1.据时间事件改变状态 2.表单元素的属性操作 3.实现密码显示隐藏 4.循环精灵图 前言 阅读使人充实,会谈使人敏捷,写作使人精确. ...
- python post 请求json文件_requests的post请求提交表单、json串和文件数据讲解
HTTP协议中没有规定post提交的数据必须使用什么编码方式,服务端根据请求头中的Content-Type字段来获取编码方式,再对数据进行解析.具体的编码方式包括如下: - application/x ...
- ajax异步请求——form表单提交 及 表单序列化提交
ajax异步请求 AJAX介绍 AJAX 指异步 JavaScript 及 XML(Asynchronous JavaScript And XML),它不是一种新的编程语言,而是一种使用现有标准的新方 ...
- html post和get请求,form表单的GET和POST请求
是HTML标签中比较复杂的标签之一,在学习中我注意到它与HTTP协议有关联,所以我做了一些总结. method="GET" 首先新建一个包含form表单的html文件,例如inde ...
- html表单上传图片获取路径,asp.net获取HTML表单File中的路径的方法
代码如下: #region 上传文件到数据库和服务器 public void FN_UpFiles() { //遍历File表单元素 HttpFileCollection files = HttpCo ...
最新文章
- C#编程(十六)----------匿名类型
- GLUT及其函数的用法整理
- Linux服务器安装NodeJs简易方法
- 分辨出谁在浏览Youtube、土豆
- poj 2696 A Mysterious Function
- Android对接实现内网无纸化会议|智慧教室|实时同屏功能
- mqadmin命令运行出错
- 基于用户的协同过滤算法
- Pytorch专题实战——激活函数(Activation Functions)
- MySQL中的主键约束和外键约束
- 社交产品方法论(八):数据分析的二三事
- 基于WebUploader、SpringMVC的断点续传
- Sentaurus TCAD 2013 在RedHat7.0 Linux系统的安装教程
- BJTU1940 铁憨憨骑士团的回文对称
- 面对已知问题和未知问题的解决思路
- Cmder | 一款命令行增强工具
- 自定义 ViewGroup,实现多功能流式布局与网格布局
- windows+onlyoffice安装
- cad在线转换_有哪些工具可以将PDF转换成CAD图纸?
- 记录一下自己的头脑风暴
热门文章
- php高等数学,中国大学《高等数学(四)》期末答案高校邦《PHP语言程序设计》见面课答案...
- vue router传参_新手使用vue-router传参时注意事项
- 中国首台千万亿次超级计算机,中国首台千万亿次超级计算机首批设备开始试用...
- linux libbz2.so.1,libbz2.so.1.0 = not found 试过了链接和设置环境变量
- micropython web ws2812_MicroPython实例之TPYBoard v102炫彩跑马灯WS2812B
- python内存管理机制错误_Python内存管理机制和垃圾回收机制的简单理解
- spring--打印hello--注解component--自动创建对象
- pynput模块—键盘鼠标操作和监听
- SpringBoot整合Mybatis-plus实现增删查改
- 动态dp模板题(树剖+dp+线段树)