FastApi笔记
学习FastApi建议直接看官方文档:官方文档
文章目录
- FastApi笔记
-
- 一、环境准备
-
- [1.1 安装Fast Api](#1.1 安装Fast Api)
- [二、第一个Restful API](#二、第一个Restful API)
-
- [2.1 创建第一个代码框架](#2.1 创建第一个代码框架)
- [2.2 运行第一个代码](#2.2 运行第一个代码)
- [2.3 Swag UI界面 (1)](#2.3 Swag UI界面 (1))
- [2.4 直接启动应用](#2.4 直接启动应用)
- [2.5 Swag UI界面 (2)](#2.5 Swag UI界面 (2))
- 三、路径参数
-
- [3.1 路径参数存在于uri当中](#3.1 路径参数存在于uri当中)
- [3.2 参数类型限定](#3.2 参数类型限定)
- [3.3 API定义的顺序影响](#3.3 API定义的顺序影响)
- [3.4 通过枚举定义参数值的可选项](#3.4 通过枚举定义参数值的可选项)
- 四、查询参数
-
- [4.1 查询参数存在于 uri 当中](#4.1 查询参数存在于 uri 当中)
- [4.2 可选查询参数](#4.2 可选查询参数)
一、环境准备
1.1 安装Fast Api
pip3 install fastapi[all]
[all] 指安装fastapi下提供的所有插件
二、第一个Restful API
2.1 创建第一个代码框架
在main.py
中写下如下代码:
python
from fastapi import FastApi
app = FastApi() # 构造一个app对象
@app.get('/helloworld') # 定义所需要开发的api
async def index(): # async为异步函数
return {'message': 'Hello World'}
# 程序到这里就拥有了/helloworld这个api
async作用(引自CSDN):
常规函数开始执行后一直运行到
return
实现退出,如果需要能够中断的函数,就需要添加async
关键字。
async
用来声明一个函数为异步函数,异步函数的特点就是能在函数执行过程中被挂起,去执行其他异步函数,等挂起条件消失后再回来执行。
因为fastapi很快,它所有基于api的定义都是异步化的,所以读用async
关键字
2.2 运行第一个代码
在终端中输入:
uvicorn main:app --reload
由于
fastapi
不具备基本的网关服务,所以它需要借助于外部的网关服务器来提供web访问的基础架构。
uvicorn
:就是一个非常高性能的SGI网关服务器。
main:app
:表示加载main.py
中的app
程序--reload
表示进行加载
运行成功后,终端可能会显示如下代码:
(venv) PS C:\Users\UserName\Desktop\First_FastApi> uvicorn main:app --reload
INFO: Will watch for changes in these directories: ['C:\\Users\\UserName\\Desktop\\First_FastApi']
INFO: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)
INFO: Started reloader process [34768] using WatchFiles
INFO: Started server process [20412]
INFO: Waiting for application startup.
INFO: Application startup complete.
INFO: 127.0.0.1:57829 - "GET / HTTP/1.1" 404 Not Found
INFO: 127.0.0.1:58012 - "GET / HTTP/1.1" 404 Not Found
"Not Found"?这就对了,因为上面的代码没有定义根
代码中补充即可:
python
from fastapi import FastAPI
app = FastAPI()
@app.get('/')
async def root():
return {'message' : 'Hello Root'}
@app.get('/helloworld')
async def read_get():
return {'message': 'hello world'}
这个时候去重新刷新网站即可,网站会显示:
{
"message": "Hello Root"
}
这里可以发现启动程序时
uvicorn main:app --reload
中最后加入--reload
的作用其实就是在刷新网页时自动加载新的保存好的代码配置
如果想要访问/helloworld
所在的api
在浏览器搜索框中改为如下地址即可,
http://127.0.0.1:8000/helloworld
返回的结果使用了jason,这就是最基本的restful api,是基于http请求的
2.3 Swag UI界面 (1)
在浏览器搜索框中将地址改为,
http://127.0.0.1:8000/docs
出现了这样的界面,在这里可以轻松的看到当前服务器中定义了哪些api。
这一点对于要开发restful api的人来讲,是很好的选择。
2.4 直接启动应用
在代码中进行如下修改即可,
python
from fastapi import FastAPI
import uvicorn # 导入uvicorn的服务调用启动服务器的方法
app = FastAPI()
@app.get('/')
async def root():
return {'message' : 'Hello Root'}
@app.get('/helloworld')
async def read_get():
return {'message': 'hello world'}
if __name__ == '__main__':
uvicorn.run("main:app", reload=True) # 和命令行中的代码一致
完成修改后,直接点击if __name__ == '__main__':
左边的绿色三角形,并在内置终端中点击网址即可在web中打开程序。
2.5 Swag UI界面 (2)
在swag ui中点击Try it out
>Execute
,也就是尝试>执行。可以做到直接向服务器发送请求并看到送回的返回结果。
三、路径参数
3.1 路径参数存在于uri当中
http://localhost:8000/users/2
python
@app.get('/users/{user_id}')
async def get_user(user_id: int):
return {'user_id': user_id}
上面两端代码分别对应 uri 和 python 中用来提取信息的代码,其中 users/ 后面的内容 2 就是路径参数,fastapi 会根据定义的格式,自动提取出参数。上述例子中,当前端输入该地址后,fastapi 会提取 2 作为 user_id 的参数。
3.2 参数类型限定
对于下面的代码:
python
from fastapi import FastAPI
import uvicorn # 导入uvicorn的服务调用启动服务器的方法
app = FastAPI()
@app.get('/users/{user_id}')
async def get_user(user_id):
return {'user': f'This is the user for {user_id}'}
if __name__ == '__main__':
uvicorn.run("main:app", reload=True) # 和命令行中的代码一致
运行后在浏览器中查看, 再次可以看到swag UI的强大之处:
上述代码中并没有指定实际的类型,有时我们需要限定输入的数据类型。如果输入的数据类型不符合输入要求的类型,需要进行报错而不是直接使用。比如上述例子中我要求
id
是整数而不能是字符串,就要加上: int
来进行类型的申明:
python
from fastapi import FastAPI
import uvicorn # 导入uvicorn的服务调用启动服务器的方法
app = FastAPI()
@app.get('/users/{user_id}')
async def get_user(user_id: int):
return {'user': f'This is the user for {user_id}'}
if __name__ == '__main__':
uvicorn.run("main:app", reload=True) # 和命令行中的代码一致
运行成功后路径参数不是 int
类型会有如下报错:
这里的报错提示是可以进行定制的,这里暂且不谈。
3.3 API定义的顺序影响
python
from fastapi import FastAPI
import uvicorn # 导入uvicorn的服务调用启动服务器的方法
app = FastAPI()
@app.get('/users/{user_id}')
async def get_user(user_id: int):
return {'user': f'This is the user for {user_id}'}
@app.get('/users/current')
async def get_current_user():
return {'user': f'This is current user.'}
if __name__ == '__main__':
uvicorn.run("main:app", reload=True) # 和命令行中的代码一致
上面代码运行后,在Web中访问
http://127.0.0.1:8000/users/12
会返回
{
"user": "This is the user for 12"
}
但是如果访问
http://127.0.0.1:8000/users/current
就会返回
{
"detail": [
{
"type": "missing",
"loc": [
"query",
"user_id"
],
"msg": "Field required",
"input": null
}
]
}
为什么会出现这种情况?
因为user/current
是满足第一种api的定义模式的格式要求,所以第一个api定义会执行并返回类型报错。换言之,fastapi并不知道你后面还定义了一个可以使用的方法。
但如如果将顺序反过来:
python
from fastapi import FastAPI
import uvicorn # 导入uvicorn的服务调用启动服务器的方法
app = FastAPI()
@app.get('/users/current')
async def get_current_user():
return {'user': f'This is current user.'}
@app.get('/users/{user_id}')
async def get_user(user_id: int):
return {'user': f'This is the user for {user_id}'}
if __name__ == '__main__':
uvicorn.run("main:app", reload=True) # 和命令行中的代码一致
功能就正常了,current
可以被正常识别,int
型也能识别出来。
说白了,这个例子告诉我们,当api的格式定义很相似的时候,我们要主要api定义的顺序,以防止某些定义不能正常使用。
也就是"小范围在前,大范围在后"。
3.4 通过枚举定义参数值的可选项
如果路径的参数是一个性别,我们该怎么提供一个选择项呢?- (男/女)。也就是如何去在 swag UI 中提供一个选择菜单的意思。
python
from fastapi import FastAPI
import uvicorn # 导入uvicorn的服务调用启动服务器的方法
from enum import Enum
app = FastAPI()
class Gender(str, Enum): # Gender 同时继承了`字符串类型` 和 `枚举类型`
male = "male"
female = "female"
@app.get('/student/{gender}')
async def get_gender(gender: Gender):
return {'student': f'This is a {gender.value} student'}
if __name__ == '__main__':
uvicorn.run("main:app", reload=True) # 和命令行中的代码一致
上述代码定义了一个 Gender 的性别类,它同时继承了字符串和枚举类型,Gender类都是一个可供枚举的字符串值,只能选择枚举可能性中的一种。
运行后在swag UI中显示如下:
这个方法对于调用者来讲没有太大差别,但对于测试者来说,有极大的方便之处。
四、查询参数
4.1 查询参数存在于 uri 当中
http://localhost:8000/users?page_index=1&page_size=10
python
from fastapi import FastAPI
import uvicorn # 导入uvicorn的服务调用启动服务器的方法
app = FastAPI()
@app.get('/users')
async def get_user(page_index: int, page_size: int):
return {'page info': f'index : {page_index} size: {page_size}'}
if __name__ == '__main__':
uvicorn.run("main:app", reload=True) # 和命令行中的代码一致
在uri中以xxx?xxx
的键值对形式来表示查询的路径参数,使用&
将它们串在一起。
4.2 可选查询参数
如果uri中只给了page_index不给page_size就叫可选查询参数
python
from fastapi import FastAPI
import uvicorn # 导入uvicorn的服务调用启动服务器的方法
from typing import Optional
app = FastAPI()
@app.get('/users')
async def get_user(page_index: int, page_size: Optional[int] = 30):
return {'page info': f'index : {page_index} size: {page_size}'}
if __name__ == '__main__':
uvicorn.run("main:app", reload=True) # 和命令行中的代码一致
在int前加一个Optional
即可,这里缺省值设为30。
可以看到,默认的值为 14,是缺省值。