fastapi是python的一个高性能web框架。它有着非常高的性能,与nodejs和go相当,和开发迅速等特点。
一、安装
pip install fastapi
pip install uvicorn
二、例子
# main.py
from fastapi import FastAPI # 导入FastAPI import uvicorn app = FastAPI() # 创建一个app实例 @app.get("/") # 编写一个路径操作装饰器 async def root(): # 编写一个路径操作函数 return {"你好!": "朋友。"} if __name__ == '__main__': uvicorn.run(app='main:app', host="127.0.0.1", port=8000, reload=True, debug=True)
注意:
- main:表示app所在的文件名
- app:表示fastapi的实例
- reload、debug:表示可以自动重启
三、运行
uvicorn main:app --reload
注意pycharm里面快捷启动—>右键run
四、路由
路由方法有 GET, POST, PUT, PATCH, DELETE 和 OPTIONS:
@app.post("/") @app.put("/") @app.delete("/") @app.get("/") @app.options("/") @app.head("/") @app.patch("/") @app.trace("/") async def root(): return {"message": "Hello World"}
五、动态路由获取参数
@app.get("/items/{item_id}") # 路径中的item_id将会被解析,传递给方法中的item_id。 async def read_item(item_id): return {"item_id": item_id}
六、在方法中定义参数类型
@app.get("/items/{item_id}") async def read_item(item_id: int): return {"item_id": item_id}
当参数item_id是非数字,将报如下错误:
{ "detail": [ { "loc": [ "path", "item_id" ], "msg": "value is not a valid integer", "type": "type_error.integer" } ] }
所有的数据类型验证,都是通过Pydantic完成的。
七、预定义路由参数
class ModelName(str, Enum): alexnet = "alexnet" resnet = "resnet" lenet = "lenet" @app.get("/model/{model_name}") async def get_model(model_name: ModelName): if model_name == ModelName.alexnet: return {"model_name": model_name, "message": "Deep Learning FTW!"} if model_name.value == "lenet": return {"model_name": model_name, "message": "LeCNN all the images"} return {"model_name": model_name, "message": "Have some residuals"}
八、路径参数
想接收一个路径参数,它本身就是一个路径,就像/files/{file_path},而这个file_path是home/johndoe/myfile.txt时,可以写成/files/{file_path:path}:
@app.get("/files/{file_path:path}") async def read_user_me(file_path: str): return {"file_path": file_path}
OpenAPI本身不支持在路径参数包含路径,但是可以当作Starlette内部的一个使用方法。
九、路由覆盖问题
@app.get("/users/me") async def read_user_me(): return {"user_id": "the current user"} @app.get("/users/{user_id}") async def read_user(user_id: str): return {"被优先匹配到:": user_id}
当user_id=me时,路由@app.get("/users/me")会被路由@app.get("/users/{user_id}")覆盖。
十、获取查询参数
@app.get("/items/") async def read_item(skip: int = 0, limit: int = 10): return skip + limit
请求http://127.0.0.1:8000/items/?skip=0&limit=2,将返回2.
请求http://127.0.0.1:8000/items/,将返回10,因为在函数内定义了默认值。
十一、多路径和查询参数
多路径和查询参数就是URL上包含了有动态的参数(动态路由),还有需要通过&分隔符提交的参数。
# http://127.0.0.1:8000/users/123456/items/items_xinxiid/?q=assa&short=True
@app.get("/users/{user_id}/items/{item_id}") async def read_user_item(user_id: int, item_id: str, q: str = None, short: bool = False): item = {"item_id": item_id, "owner_id": user_id} if q: item.update({"q": q}) if not short: item.update( {"description": "This is an amazing item that has a long description"} ) return item
注意:查询参数如果设置了默认值,则是可选参数。
十二、使用Optional定义查询参数的类型
from typing import Optional @app.get("/items/{item_id}") async def read_user_item(item_id: str, limit: Optional[int] = None): item = {"item_id": item_id, "limit": limit} return item
十三、Query参数
以前通常是使用wtform来定义提交的字段信息的类似或可选或长度类型。在Fastapi里面,我们是通过: from fastapi import FastAPI, Query 中的Query来定义:
from fastapi import FastAPI, Query app = FastAPI() @app.get("/items/") async def read_items(q: str = Query(None, min_length=3,max_length=50),regex="^fixedquery$"): results = {"items": [{"item_id": "Foo"}, {"item_id": "Bar"}]} if q: results.update({"q": q}) return results
十四、Query参数多值列表
# http://127.0.0.1:8000/items/?q=foo&q=bar from typing import List from fastapi import FastAPI, Query app = FastAPI() @app.get("/items/") async def read_items(q: List[str] = Query(["foo", "bar"])): # <!--也可以使用list直接代替List[str]:--> query_items = {"q": q} return query_items
访问 http://127.0.0.1:8000/items/ 返回 {"q":["foo","bar"]}
访问 http://127.0.0.1:8000/items/?q=123&q=456 返回 {"q":["123","456"]}
十五、Path模块
Fastapi自带的Path也可以对参数进行校验。
from fastapi import FastAPI, Path app = FastAPI() @app.get("/items/{item_id}") async def read_items(q: str, item_id: int = Path(..., title="The ID of the item to get")): results = {"item_id": item_id} if q: results.update({"q": q}) return results
对路径参数做大于或等于操作,路径参数的值必须不小于ge的值:
from fastapi import FastAPI, Path app = FastAPI() @app.get("/items/{item_id}") async def read_items(*, item_id: int = Path(..., title="The ID of the item to get", ge=1), q: str ): results = {"item_id": item_id} if q: results.update({"q": q}) return results
十六、多个Request Body的提交
更复杂的业务其实会存在多体的Boay的提交,
结束!