FastApi快速上手
简介
快速启动
环境配置
- Python版本建议3.8及以上(此教程使用为3.8.9)
- Pycharm
创建项目
pycharm新建项目
pip 安装相关包
如果电脑上只有一个python 那直接pip即可
1
2
3pip3 install fastapi
# 启动服务所需
pip3 install "uvicorn[standard]"
不想费劲的话,文末给的有压缩包,项目内有requirements.txt
- 可直接pip install -r requirements.txt
新建main.py
1
2
3
4
5
6
7from fastapi import FastAPI
app = FastAPI()
@app.get('/getIndex')
def index():
return {"data": {"msg": "hello word", "code": 200}}在命令行中启动服务
1
uvicorn main:app --reload
在浏览器中访问http://127.0.0.1:8000,这个时候就可以看到根据路径("/"),返回的JSON响应数据了
接口文档介绍
fastapi启动服务时候,会自带一份接口文档,我们访问http://127.0.0.1/docs即可打开
以下是各个参数对应图
增删查改数据介绍
- 众所周知,在HTTP请求方法中
- GET:请求获取(查询)
- POST:请求提交(新增)
- PUT:请求更新已存在的资源(修改)
- DELETE:请求删除
ORM介绍
为了更直观的看到数据的变化,我们采用连接数据库的操作
在操作数据库之前,我们需要了解ORM(对象关系映射)
这个ORM我们可以理解为,在我们Python class对象对应的是数据库中的表
类里面tablename=xxxx,等于表名
类属性 = 表字段
类属性里面的Column内的属性,INTEGER整型,String字符串,primary_key主键,autoincrement主键自增,default默认值
下面开始链接数据库,fastapi连接数据库操作包准备(mysql为例)
1
2pip3 install sqlalchemy
pip3 install pymysql我们自动化框架设计会分层
元素层
页面层
数据层
用例层
对于xx系统级别项目,大概会分(以java为例)
- 配置层(网关,数据库等)
- entity类(各种对象如订单、商品、代理区域)
- mapper层(查询数据库数据)
- service(通过扩展接口使用mapper层获取数据)
controller(专注业务实现)
每层的作用都是专注于自己内部,实现最大化解耦
根据以上,我们在fasapi项目里面也可以分层如图(参照网上)
链接数据库
首先我们新建database.py,配置好数据库连接,以mysql为例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22# database.py
from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
SQLALCHEMY_DATABASE_URL = "mysql+pymysql://账号:密码@地址:端口/database"
# echo=True表示引擎将用repr()函数记录所有语句及其参数列表到日志
engine = create_engine(
SQLALCHEMY_DATABASE_URL
)
# SQLAlchemy中,CRUD是通过会话进行管理的,所以需要先创建会话,
# 每一个SessionLocal实例就是一个数据库session
# flush指发送到数据库语句到数据库,但数据库不一定执行写入磁盘
# commit是指提交事务,将变更保存到数据库文件中
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
# 创建基本映射类
Base = declarative_base()创建models.py文件,进行ORM映射
如果是已有的表,那么在进行映射时候一定注意字段对应
类属性字段名=数据库字段名
不对应会报错
1
2
3
4
5
6
7
8
9
10
11
12
13
14from sqlalchemy import Column, String, INTEGER
from database import Base, engine
# 创建ORM映射 字段根据数据库字段来,没有库会新建
class Customer(Base):
__tablename__ = 'customer'
uid = Column(INTEGER, primary_key=True, autoincrement=True)
username = Column(String(20))
remark = Column(String(20))
Base.metadata.create_all(bind=engine)
创建schemas.py(请求体数据模型),主要是为了传入一个对象时候,如新增客户时候,这个客户有姓名和备注两个字段,以对象的显示传入进去
fasapi会将这种对象以字典形式传入
1
2
3
4
5
6
7
8class CustomerBase(BaseModel):
username: str
remark: str
class Config:
from_attributes = True
# 配置orm_mode除了可以让pydantic读取字典类型的数据,还支持读取属性数据,比如sqlalchemy模型的数据
# 这样pydantic数据模型就可以兼容sqlalchemy数据模型,可以直接在路径操作函数中直接返回sqlalchemy数据模型关于 from_attributes = True介绍
配置orm_mode除了可以让pydantic读取字典类型的数据,还支持读取属性数据,比如sqlalchemy模型的数据
这样pydantic数据模型就可以兼容sqlalchemy数据模型,可以直接在路径操作函数中直接返回sqlalchemy数据模型
增加数据
创建curd.py文件,编写新增时如何操作数据库
db: Session 获取db链接信息
customer: schemas.CustomerBase,相当于将CustomerBase这个里面的属性给到customer,在下面使用customer时候可直接customer.xxx属性
1 |
|
回到main文件中编写路由及导入数据库等信息
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
27
28
29
30
31
32
33
34
35
36
37
38from fastapi import FastAPI, Depends
from sqlalchemy.orm import Session
import crud
import models
import schemas
from database import SessionLocal
from schemas import StudentCreate, CustomerBase
app = FastAPI(title="我店测试平台接口文档",
version="0.0.1",
description=description,
license_info={"name": "Apache 2.0","url": "https://www.apache.org/licenses/LICENSE-2.0.html"}
)
def get_db():
"""
sessionmaker创建了一个工厂类,在创建这个工厂类时我们配置了参数绑定了引擎,
将其赋值给SessionLocal
每次实例化SessionLocal都会创建一个绑定了引擎的SessionLocal
这样这个SessionLocal在访问数据库时都会通过这个绑定好的引擎来获取连接资源
"""
db = SessionLocal()
try:
yield db
finally:
db.close()
@app.get('/getIndex', summary="首页测试", tags=['首页'])
def index():
return {"data": {"msg": "hello word", "code": 200}}
@app.post('/api/customerAdd', summary="新增客户", tags=['客户信息相关'], response_model=schemas.CustomerBase)
def customer_add(customer: CustomerBase, db: Session = Depends(get_db)):
return crud.create_customer(db=db, customer=customer)response_model:响应体模型映射,可在请求成功后返回添加到数据
Depends: 依赖get_db获取资源操作数据库
customer: CustomerBase:模型映射,在自带接口文档中的请求体,可自动解析成这个CustomerBase里面的字段属性:username和remark
测试
我们可以点开接口文档对应的接口路径,
点击try out按钮
输入请求体
点击excute执行
可以看到response body已经响应,为我们添加的数据
此时我们去数据库查看,数据已经写入
查询数据(根据UID)
让我们回到curd.py添加根据客户id查找对应信息的操作
1
2
3
4
5
6
7
8
9
10
11
12def get_customer(db: Session, customer_id: int):
"""
# 根据id获取详情
:param db:
:param customer_id:
:return:
"""
# 将传入进来的customer_id,在数据库中查询uid等于customer_id的数据
# query查询的表
# filter过滤条件
# first()获取第一个数据
return db.query(models.Customer).filter(models.Customer.uid == customer_id).first()回到main.py内编写路由和传入id等信息操作
1
2
3
4
5
6
7
8
9
10@app.get('/api/customerDetail', summary="客户详情", tags=['客户信息相关'])
def customer_detail(customer_id: int, db: Session = Depends(get_db)):
"""
客户详情
- customer_id: 客户id
"""
customer = crud.get_customer(db=db, customer_id=customer_id)
if customer is None:
return {"msg": "未找到此客户", "code": 400}
return {"msg": "success", "code": 200, "data": customer}
测试
刷新接口文档,可以看到接口已经在上面,让我们调试接口,还是try out后输入请求体,点击执行
可以看到uid=9的客户信息
如果没有uid对应的信息,则会根据业务判断,返回错误
修改数据(根据UID)
在crud.py文件内编写根据uid修改信息操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17def update_customer(db: Session, customer_id: int, customer: schemas.CustomerBase):
"""
根据id更新客户信息
:param db:
:param customer_id:
:param customer:
:return:
"""
# 首先查询出要更新的数据
db_customer = db.query(models.Customer).filter(models.Customer.uid == customer_id).first()
# 更新名称
db_customer.username = customer.username
# 更新备注
db_customer.remark = customer.remark
db.commit()
db.refresh(db_customer)
return db_customer在main.py文件内编写路由等信息操作
1
2
3
4
5
6
7
8
9
10@app.put('/api/customerUpdate', summary="客户更新", tags=['客户信息相关'], response_model=schemas.CustomerBase)
def customer_update(customer_id: int, customer: CustomerBase, db: Session = Depends(get_db)):
"""
参数列表
- customer_id: 客户id
- username: 客户姓名
- remark: 客户备注
"""
# 传入id和对象信息
return crud.update_customer(db=db, customer_id=customer_id, customer=customer)
测试
刷新接口文档,开始调试,输入id和请求体,点击执行,可看到响应成功我们修改的数据
再次验证,用刚才写好的根据id查询信息的接口调用,可以看到确实修改成功
删除数据(根据UID)
在crud.py文件内编写根据uid删除信息操作
1
2
3
4
5
6
7
8
9
10
11
12
13def delete_customer(db: Session, customer_id: int):
"""
根据id删除客户信息
:param db:
:param customer_id:
:return:
"""
# 获取要删除的客户信息
db_customer = db.query(models.Customer).filter(models.Customer.uid == customer_id).first()
# 执行delete操作
db.delete(db_customer)
db.commit()
return db_customer在main.py文件内编写路由等信息操作
1
2
3
4
5
6
7@app.delete('/api/customerDel', summary="客户删除", tags=['客户信息相关'])
def customer_del(customer_id: int, db: Session = Depends(get_db)):
"""
参数列表
- customer_id: 客户id
"""
return crud.delete_customer(db=db, customer_id=customer_id)
测试
刷新接口,填入uid,点击执行,可以看到被删除的对象信息
用根据uid查询信息接口获取信息,可以看到未获取到,数据库也确实删除了