前言
近期接触了一些开源大模型应用服务,发现很多用的都是FastAPI web框架,于是乎研究了一下它的优势,印象最深有两个:一个是它的异步处理性能比较好,二是它可以类似java swagger的API交互文档,这个对应前后端分离多人开发非常友好。之前总结过Vue和Flask实现前后端分离,这次同样借个小项目实践、并总结下Vue和FastAPI实现前后端分离。
FastAPI:
- FastAPI 是一个现代化的 Web 框架,基于 Python 3.7+ 的类型提示和异步编程技术。
- FastAPI 遵循 OpenAPI(以前称为 Swagger)标准,可以自动生成交互式 API 文档。
- FastAPI 提供了自动数据验证、自动文档生成等强大的功能,可以显著减少开发工作量。
- FastAPI 基于 Starlette 框架构建,支持异步请求处理,能够处理高并发和高负载的场景。
准备
项目需求及分析:
有个抓拍人脸并保存人脸截图的算法,在版本发布前想要对其效果收集主观评价。于是开发一个简单的内部在线评分工具会方便大家操作以及最后结果的汇总。照样采用vue框架,后端就尝试下FastAPI。
在开始开发前,我们先去github上看看有没有类似的开源项目,如果有现成的项目框架可以用,我们只需在上面添加或改动实现我们的业务功能即可,一定程度上可以大大缩短开发周期。
由于评分工具需要用户信息,所以需要用户登录及用户管理功能。
于是找到一个基本符合我们要求的开源项目:
GitHub - JohnDoe1996/fastAPI-vue: FastAPI-vue
开源项目源码目录如上图,前端代码在frontend/dashboard目录下,vue框架;后端代码在backend/app下,采用FastAPI。
前端
关于前端开发环境准备,可参考Vue和Flask实现前后端分离,在此不做赘述。
将开源项目的前端代码在pycharm中打开,安装依赖库,npm install,启动服务,在浏览器可以正常打开页面。(如果验证码不显示没关系,因为我们还没有启动后端服务)
至此,开发环境准备妥当,下面可进行前端代码的开发。
前端主要涉及两个页面,任务列表页面及图片展示和投票提交页面,采用ElementUI组件库。
要实现前后端通信,我们需要在前端项目中相应位置配置后端服务地址:
后端
打开pycharm,打开backend/app项目,配置venv。工程目录如下:
业务功能涉及的后端接口较简单,其实主要是对mysql数据库的CURD。但对于FastAPI,不同于Flask的是它可以定义数据模型,schemas用于定义API的输入输出数据的结构,可以提高API的稳定性、可维护性和安全性,同时提升开发效率。
首先,我们通过Pydantic库来定义数据模型,这个数据模型可以用作请求体、响应体的参数中。
from pydantic import BaseModel
class TaskDataSchema(BaseModel):
name: str
type: int = 0
resource_path: str
remark: str = ""
status: int = 0
order_num: int = 0
class ResourceGroupSchema(BaseModel):
name: str
type: int = 0
path: str
remark: str = ""
status: int = 0
order_num: int = 0
task_data_id: int
接着,在路由操作函数中,请求参数可以使用上面定义的数据模型,如ResourceDataSchema作为请求体结构。当客户端发送 POST、PUT 等请求时,FastAPI 会自动解析请求体,并将数据转换为定义的 Pydantic 模型。
from .schemas import ResourceDataSchema
from .curd.curd_resource_group import curd_resource_group
from common import deps
from ..permission.models import Users
router = APIRouter()
@router.post("/resource/data", summary="添加资源", tags=["task"])
async def addResourceData(*,
db: Session = Depends(deps.get_db),
u: Users = Depends(deps.user_perm(["task:image-list:get"])),
obj: ResourceDataSchema
):
curd_resource_data.create(db, obj_in=obj, creator_id=u['id'])
return respSuccessJson()
最终效果:
生产环境部署
采用docker-compose部署,目录结构如下:
docker-compose.yml如下:
version: '3'
services:
nginx:
image: privatehub.xxxx.com/nginx:v2.2
volumes:
- /fastAPI-vue/frontend/nginx.conf:/etc/nginx/nginx.conf
- /fastAPI-vue/frontend/conf.d:/etc/nginx/conf.d
- /fastAPI-vue/frontend/html:/var/www/html
- /etc/localtime:/etc/localtime
ports:
- 8999:8080
restart: always
backend:
build: /fastAPI-vue/backend
volumes:
- $PWD/backend:/backend
ports:
- 8099:8899
restart: always
nginx是前端服务,backend是后端服务,主要指定镜像、端口映射,进行目录挂载。
FastAPI-vue/backend中的Dockerfile如下:
# 基础镜像
FROM privatehub.xxx.com/python:v1.0
# 作者
MAINTAINER xxxx
# 设置工作目录
COPY app/requirements.txt /tmp
WORKDIR /backend/app
# 安装依赖库
RUN pip install --no-cache-dir -r /tmp/requirements.txt
# 启动命令
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8899"]
执行命令启动服务:
docker-compose up -d --build