文章目录

  • 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}

  • 可在一个路径操作中声明多个 FileForm 参数,但不能同时声明要接收 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相关推荐

  1. html中只能上传文件word,HTML文件表单,接受Word文档(HTML file form, accept Word documents)...

    HTML文件表单,接受Word文档(HTML file form, accept Word documents) 我在这里遇到了一个奇怪的问题. (不管怎样,或者我只是忽略了一些非常简单的东西.) 我 ...

  2. angularjs 表单校验指令_angular4.0的模板式表单、响应式表单及其错误提示

    模板式表单 NgForm.NgModel.NgModelGroup是FormModule里的内容,NgForm会自动拦截标准的表单处理事件(eg.提交),angular用ngSubmit代替标准的表单 ...

  3. ios php 表单提交图片上传,axios发送post请求提交图片表单步骤详解

    这次给大家带来axios发送post请求提交图片表单步骤详解,axios发送post请求提交图片表单的注意事项有哪些,下面就是实战案例,一起来看一下. DOME 接口const userUploadA ...

  4. js操作元素:改变元素内容有两种方式: interText 和 innerHTML的区别, 常用的元素的属性操作, 仿电脑系统时间问好 ,表单元素的属性操作 ,案例:仿京东显示隐藏密码 ,样式属性操作

    文章目录 操作元素 改变元素内容有两种方式: interText 和 innerHTML的区别 常用的元素的属性操作 案例:仿电脑系统时间问好 表单元素的属性操作 案例:仿京东显示隐藏密码 样式属性操 ...

  5. 【JavaScript-事件②】表单元素的属性操作,密码显示隐藏的实现

    目录 前言 1.据时间事件改变状态 2.表单元素的属性操作 3.实现密码显示隐藏 4.循环精灵图 前言 阅读使人充实,会谈使人敏捷,写作使人精确.                            ...

  6. python post 请求json文件_requests的post请求提交表单、json串和文件数据讲解

    HTTP协议中没有规定post提交的数据必须使用什么编码方式,服务端根据请求头中的Content-Type字段来获取编码方式,再对数据进行解析.具体的编码方式包括如下: - application/x ...

  7. ajax异步请求——form表单提交 及 表单序列化提交

    ajax异步请求 AJAX介绍 AJAX 指异步 JavaScript 及 XML(Asynchronous JavaScript And XML),它不是一种新的编程语言,而是一种使用现有标准的新方 ...

  8. html post和get请求,form表单的GET和POST请求

    是HTML标签中比较复杂的标签之一,在学习中我注意到它与HTTP协议有关联,所以我做了一些总结. method="GET" 首先新建一个包含form表单的html文件,例如inde ...

  9. html表单上传图片获取路径,asp.net获取HTML表单File中的路径的方法

    代码如下: #region 上传文件到数据库和服务器 public void FN_UpFiles() { //遍历File表单元素 HttpFileCollection files = HttpCo ...

最新文章

  1. C#编程(十六)----------匿名类型
  2. GLUT及其函数的用法整理
  3. Linux服务器安装NodeJs简易方法
  4. 分辨出谁在浏览Youtube、土豆
  5. poj 2696 A Mysterious Function
  6. Android对接实现内网无纸化会议|智慧教室|实时同屏功能
  7. mqadmin命令运行出错
  8. 基于用户的协同过滤算法
  9. Pytorch专题实战——激活函数(Activation Functions)
  10. MySQL中的主键约束和外键约束
  11. 社交产品方法论(八):数据分析的二三事
  12. 基于WebUploader、SpringMVC的断点续传
  13. Sentaurus TCAD 2013 在RedHat7.0 Linux系统的安装教程
  14. BJTU1940 铁憨憨骑士团的回文对称
  15. 面对已知问题和未知问题的解决思路
  16. Cmder | 一款命令行增强工具
  17. 自定义 ViewGroup,实现多功能流式布局与网格布局
  18. windows+onlyoffice安装
  19. cad在线转换_有哪些工具可以将PDF转换成CAD图纸?
  20. 记录一下自己的头脑风暴

热门文章

  1. php高等数学,中国大学《高等数学(四)》期末答案高校邦《PHP语言程序设计》见面课答案...
  2. vue router传参_新手使用vue-router传参时注意事项
  3. 中国首台千万亿次超级计算机,中国首台千万亿次超级计算机首批设备开始试用...
  4. linux libbz2.so.1,libbz2.so.1.0 = not found 试过了链接和设置环境变量
  5. micropython web ws2812_MicroPython实例之TPYBoard v102炫彩跑马灯WS2812B
  6. python内存管理机制错误_Python内存管理机制和垃圾回收机制的简单理解
  7. spring--打印hello--注解component--自动创建对象
  8. pynput模块—键盘鼠标操作和监听
  9. SpringBoot整合Mybatis-plus实现增删查改
  10. 动态dp模板题(树剖+dp+线段树)