0%

Python实现Web API

基于FastAPI和uvicorn开发

  • FastAPI是一个高效的异步Web框架

  • uvicorn是快速的http服务器框架

  • 详情:FastAPI

代码示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
import uvicorn


app = FastAPI()

# 处理跨域
app.add_middleware(
CORSMiddleware,
allow_origins=["*"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"]
)

@app.get('/')
def read_root():
return {"hello" : "world"}

@app.get("/items")
def read_item(item_id:int, q:str = null):
return{"item_id" : item_id, "msg":q}

if __name__ == '__main__':
uvicorn.run(app = app, host = "0.0.0.0", port = 8000)

@app.post下的函数处理post请求,@app.post('/')表示路由,本例中post的url为localhost:8000,如果改为@app.post('/p'),那么post时的url应为localhost:8000/p

其他的请求同理

运行服务器

1
uvicorn <填入文件名>:<填入FastAPI实例名> --reload

我的程序文件名为webtest.py,实例名为app,所以我的指令为:

1
uvicorn webtest:app --reload

完整指令是:

1
uvicorn <文件名>:<实例名> --reload --host 192.XXX.XXX --port xxxx

其中,reload是自动重启,修改源文件后服务器自动重启,后面的是指定主机地址和端口号,在实例程序中单独设置了,所以不需要再在命令行中设置

相关文档:Uvicorn

HTML调用

HTML调用与调用一般的REST API形式相同,这里使用jQuery发出请求

1
2
3
4
5
6
7
$.get("http://127.0.0.1:8000/items",
{
"item_id" : 1
},
function(data){
console.log(data);
})

html发出get请求

关于POST

POST基础实现

如果你像网上很多示例一样写POST,并用jQuery调用

后端:

1
2
3
@app.post('/')
def read_model(msg:str):
return {"message":msg}

前端:

1
2
3
4
5
6
7
8
$.post("http://127.0.0.1:8000",
{
"msg" : "测试数据"
},
function(data){
console.log(data);
},
"json")

那么你会发现服务器返回422错误码,说你的数据格式不正确

post发生422错误

这个问题之前在用.net core开发web api时就发现过,当时的解决方法是在参数前加上[FromForm]

像这样:

1
2
3
// 这里是c#代码
[HttpPost]
public void fun([FromForm] Item item)

这是因为看似jQuery传参是一个json,但实际上还是以Form形式传递的,在python这里也要这样操作,在参数后面加上= Form(<参数>)

修改后的后端代码:

1
2
3
4
5
from fastapi import FastAPI, Form

@app.post('/')
def read_model(msg:str = Form(...)):
return {"message":msg}

前端不用修改,这次可以正常POST了

成功post

关于Form(<para>)中的参数

  • 如果写Form(...)表示这个参数不可省略
  • 如果写Form("这是默认数据")表示这个参数缺省时的默认参数为一个字符串:”这是默认数据”
  • 如果写Form(None)表示这个参数缺省时的默认值为空

使用模型类

模型使用pydantic
详情:pydantic

我想开发web api主要是因为想要接收MyQQ机器人HTMLAPI的回调请求,虽然无法接收form形式的post请求,但json类型还是可以的。

创建模型类:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from pydantic import BaseModel

class MSG_CALL_BACK(BaseModel):
MQ_robot: str
MQ_type: int
MQ_type_sub: int
MQ_fromID: str
MQ_fromQQ: str
MQ_passiveQQ: str
MQ_msg: str
MQ_msgSeq: str
MQ_msgID: str
MQ_msgData: str
MQ_timestamp: str

编写post处理:

1
2
3
4
@app.post('/')
def read_model(
item:MSG_CALL_BACK):
return {"status":1}

即使不指定item的类型在python中也是完全可行的,只不过指定类型后在取item中的值时会有代码提示,也便于代码的理解

关于FastAPI中模型类和Form相关的问题: