FastAPI教程进阶(一)

一个简单的栗子

1
2
3
4
5
6
7
8
from fastapi import FastAPI

app = FastAPI()


@app.get("/")
async def root():
return {"message": "Hello World"}

FASTAPI继承Starlette,因此在Starlette中的所有可调用的对象在FASTAPI中可以直接引用

编写步骤

步骤一:导入FastAPI

1
from fastapi import FastAPI

步骤二:创建FastAPI实例

1
app = FastAPI()

步骤三:创建访问路径

1
@app.get("/")

这个路径告诉FastAPI,该装饰器下的方法是用来处理路径是“/”的GET请求

步骤四:定义方法,处理请求

1
async def root():

步骤五:返回响应信息

1
return {"message": "Hello World"}

步骤六:运行

1
uvicorn main:app --reload

获取路径参数

1
2
3
4
5
6
7
8
from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id):
return {"item_id": item_id}

路径中的item_id将会被解析,传递给方法中的item_id。请求http://127.0.0.1:8000/items/foo会返回如下结果:

1
{"item_id":"foo"}

也可以在方法中定义参数类型:

1
2
3
4
5
6
7
8
from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: int):
return {"item_id": item_id}

继续请求http://127.0.0.1:8000/items/3,会返回

1
{"item_id":3}

此时的item_id是int类型的3,而不是string类型,这是因为FastAPI在解析请求时,自动根据声明的类型进行了解析
如果请求http://127.0.0.1:8000/items/foo,此时会返回:

1
2
3
4
5
6
7
8
9
10
11
12
{
"detail": [
{
"loc": [
"path",
"item_id"
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}

这是因为foo并不能转换成int类型。请求http://127.0.0.1:8000/items/4.2也会出现上述错误

所有的数据类型验证,都是通过Pydantic完成的

如果想对路径参数做一个预定义,可以使用Enum:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from enum import Enum

from fastapi import FastAPI


class ModelName(str, Enum):
alexnet = "alexnet"
resnet = "resnet"
lenet = "lenet"


app = FastAPI()


@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"}

打开http://127.0.0.1:8000/docs:

除此之外,假如想接收一个路径参数,它本身就是一个路径,就像/files/{file_path},而这个file_path是home/johndoe/myfile.txt时,可以写成/files/{file_path:path}:

1
2
3
4
5
6
7
8
from fastapi import FastAPI

app = FastAPI()


@app.get("/files/{file_path:path}")
async def read_user_me(file_path: str):
return {"file_path": file_path}
OpenAPI本身不支持在路径参数包含路径,但是可以当作Starlette内部的一个使用方法

此时访问http://127.0.0.1:8000/files/home/johndoe/myfile.txt,返回:

1
{"file_path":"home/johndoe/myfile.txt"}

如果将路径改为/files/{file_path},会返回:

1
{"detail":"Not Found"}

获取查询参数

这里依旧是一个例子:

1
2
3
4
5
6
7
8
9
10
from fastapi import FastAPI

app = FastAPI()

fake_items_db = [{"item_name": "Foo"}, {"item_name": "Bar"}, {"item_name": "Baz"}]


@app.get("/items/")
async def read_item(skip: int = 0, limit: int = 10):
return fake_items_db[skip : skip + limit]

尝试访问http://127.0.0.1:8000/items/?skip=0&limit=2,返回:

1
[{"item_name":"Foo"},{"item_name":"Bar"}]

尝试访问http://127.0.0.1:8000/items/,返回:

1
[{"item_name":"Foo"},{"item_name":"Bar"},{"item_name":"Baz"}]

由于我们在定义方法的时候,分别赋予skip和limit默认值,当不添加querystring时,会使用默认值。当然,我们也可以将默认值赋值为None:

1
2
3
4
5
6
7
8
9
10
from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_item(item_id: str, q: str = None):
if q:
return {"item_id": item_id, "q": q}
return {"item_id": item_id}

此时,我们请求http://127.0.0.1:8000/items/1?q=qqq:

1
{"item_id":"1","q":"qqq"}

值得放心的一点是,FastAPI很聪明,他知道参数来自哪里~

假如,我们不给参数默认值会发生什么情况呢?这里还是一个例子:

1
2
3
4
5
6
7
8
9
from fastapi import FastAPI

app = FastAPI()


@app.get("/items/{item_id}")
async def read_user_item(item_id: str, needy: str):
item = {"item_id": item_id, "needy": needy}
return item

继续请求http://127.0.0.1:8000/items/1,会发现,返回报错:

1
2
3
4
5
6
7
8
9
10
11
12
{
"detail": [
{
"loc": [
"query",
"needy"
],
"msg": "field required",
"type": "value_error.missing"
}
]
}

-------------本文结束 感谢您的阅读-------------
如果觉得我的文章对您有用,请随意打赏.您的支持将鼓励我继续创作!

  • 本文标题: FastAPI教程进阶(一)
  • 文章作者: 永夜初晗凝碧天
  • 发布时间: 2020年01月15日 - 10:01:62
  • 更新时间: 2020年01月15日 - 10:01:75
  • 本文链接: https://yongnights.github.io/2020/01/15/fastapi教程进阶(一)/
  • 版权声明: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。