FastApi快速上手

简介

  1. 本教程为参考菜鸟教程官方教程制作而成
  2. 自身实践+文档制作大约4h
  3. 不足之处欢迎指出,多多包涵🌹

快速启动

环境配置

  1. Python版本建议3.8及以上(此教程使用为3.8.9)
  2. Pycharm

创建项目

  1. pycharm新建项目

  2. pip 安装相关包

    1. 如果电脑上只有一个python 那直接pip即可

      1
      2
      3
      pip3 install fastapi
      # 启动服务所需
      pip3 install "uvicorn[standard]"
  3. 不想费劲的话,文末给的有压缩包,项目内有requirements.txt

    1. 可直接pip install -r requirements.txt
  4. 新建main.py

    1
    2
    3
    4
    5
    6
    7
    from fastapi import FastAPI

    app = FastAPI()

    @app.get('/getIndex')
    def index():
    return {"data": {"msg": "hello word", "code": 200}}
  5. 在命令行中启动服务

    1
    uvicorn main:app --reload  
  6. 在浏览器中访问http://127.0.0.1:8000,这个时候就可以看到根据路径("/"),返回的JSON响应数据了

image-20241012133534068

接口文档介绍

  1. fastapi启动服务时候,会自带一份接口文档,我们访问http://127.0.0.1/docs即可打开

  2. 以下是各个参数对应图

    image-20241012133641262

增删查改数据介绍

  1. 众所周知,在HTTP请求方法中
    1. GET:请求获取(查询)
    2. POST:请求提交(新增)
    3. PUT:请求更新已存在的资源(修改)
    4. DELETE:请求删除

ORM介绍

  1. 为了更直观的看到数据的变化,我们采用连接数据库的操作

    1. 在操作数据库之前,我们需要了解ORM(对象关系映射)

    2. 这个ORM我们可以理解为,在我们Python class对象对应的是数据库中的表

      1. 类里面tablename=xxxx,等于表名

      2. 类属性 = 表字段

      3. 类属性里面的Column内的属性,INTEGER整型,String字符串,primary_key主键,autoincrement主键自增,default默认值

        image-20241012133706580

  2. 下面开始链接数据库,fastapi连接数据库操作包准备(mysql为例)

    1
    2
    pip3 install sqlalchemy
    pip3 install pymysql
  3. 我们自动化框架设计会分层

    1. 元素层

    2. 页面层

    3. 数据层

    4. 用例层

    5. 对于xx系统级别项目,大概会分(以java为例)

      1. 配置层(网关,数据库等)
      2. entity类(各种对象如订单、商品、代理区域)
      3. mapper层(查询数据库数据)
      4. service(通过扩展接口使用mapper层获取数据)
    6. controller(专注业务实现)

    7. 每层的作用都是专注于自己内部,实现最大化解耦

    8. 根据以上,我们在fasapi项目里面也可以分层如图(参照网上)

      image-20241012133726141

链接数据库

  1. 首先我们新建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()
  2. 创建models.py文件,进行ORM映射

    1. 如果是已有的表,那么在进行映射时候一定注意字段对应

      1. 类属性字段名=数据库字段名

      2. 不对应会报错

        1
        2
        3
        4
        5
        6
        7
        8
        9
        10
        11
        12
        13
        14
        from 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)
  3. 创建schemas.py(请求体数据模型),主要是为了传入一个对象时候,如新增客户时候,这个客户有姓名和备注两个字段,以对象的显示传入进去

    1. fasapi会将这种对象以字典形式传入

      1
      2
      3
      4
      5
      6
      7
      8
      class CustomerBase(BaseModel):
      username: str
      remark: str

      class Config:
      from_attributes = True
      # 配置orm_mode除了可以让pydantic读取字典类型的数据,还支持读取属性数据,比如sqlalchemy模型的数据
      # 这样pydantic数据模型就可以兼容sqlalchemy数据模型,可以直接在路径操作函数中直接返回sqlalchemy数据模型
    2. 关于 from_attributes = True介绍

      1. 配置orm_mode除了可以让pydantic读取字典类型的数据,还支持读取属性数据,比如sqlalchemy模型的数据

      2. 这样pydantic数据模型就可以兼容sqlalchemy数据模型,可以直接在路径操作函数中直接返回sqlalchemy数据模型

增加数据

  1. 创建curd.py文件,编写新增时如何操作数据库

    1. db: Session 获取db链接信息

    2. customer: schemas.CustomerBase,相当于将CustomerBase这个里面的属性给到customer,在下面使用customer时候可直接customer.xxx属性

      image-20241012133757919

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from sqlalchemy.orm import Session
import models, schemas

def create_customer(db: Session, customer: schemas.CustomerBase):
"""
新增客户信息
:param db:
:param customer:
:return:
"""
# 将传入的username和remark赋值给变量db_customer
db_customer = models.Customer(username=customer.username, remark=customer.remark)
# 将db_customer添加到数据库中
db.add(db_customer)
# 提交到数据库中
db.commit()
# 刷新数据库中的数据
db.refresh(db_customer)
return db_customer
  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
    38
    from 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)
    1. response_model:响应体模型映射,可在请求成功后返回添加到数据

    2. Depends: 依赖get_db获取资源操作数据库

    3. customer: CustomerBase:模型映射,在自带接口文档中的请求体,可自动解析成这个CustomerBase里面的字段属性:username和remark

      image-20241012133817973

测试

  1. 我们可以点开接口文档对应的接口路径,

  2. 点击try out按钮

    image-20241012133839955

  3. 输入请求体

  4. 点击excute执行

    image-20241012133909609

  5. 可以看到response body已经响应,为我们添加的数据

    image-20241012133924758

  6. 此时我们去数据库查看,数据已经写入

    image-20241012133936735

查询数据(根据UID)

  1. 让我们回到curd.py添加根据客户id查找对应信息的操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    def 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()
  2. 回到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}

测试

  1. 刷新接口文档,可以看到接口已经在上面,让我们调试接口,还是try out后输入请求体,点击执行

    1. 可以看到uid=9的客户信息

      image-20241012133955534

    2. 如果没有uid对应的信息,则会根据业务判断,返回错误

      image-20241012134012107

修改数据(根据UID)

  1. 在crud.py文件内编写根据uid修改信息操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    def 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
  2. 在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)

测试

  1. 刷新接口文档,开始调试,输入id和请求体,点击执行,可看到响应成功我们修改的数据

  2. 再次验证,用刚才写好的根据id查询信息的接口调用,可以看到确实修改成功

    image-20241012134108093

删除数据(根据UID)

  1. 在crud.py文件内编写根据uid删除信息操作

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    def 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
  2. 在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)

测试

  1. 刷新接口,填入uid,点击执行,可以看到被删除的对象信息

  2. 用根据uid查询信息接口获取信息,可以看到未获取到,数据库也确实删除了

    image-20241012134154094

    image-20241012134231766

接口文档最终效果

image-20241012134255078