Fastapi之ORM

1.Tortoise ORM

  • Tortoise ORM是一个易于使用的ORM(Object Relational Mapper),灵感来自Django,不多做介绍

2.模型定义

from tortoise import fields
from tortoise.models import Model


class DateTimeModel(Model):
    created_at = fields.DatetimeField(auto_now_add=True, description="创建时间")
    updated_at = fields.DatetimeField(auto_now=True, null=True, description="更新时间")

    class Meta:
        abstract = True


class GroupModel(DateTimeModel):
    uuid = fields.UUIDField(source_field="uuid", pk=True, unique=True, description="用户组唯一标识")
    name = fields.CharField(source_field="username", max_length=64, description="用户组名称")
    parent_uuid = fields.CharField(source_field="parent_uuid", max_length=32, null=True)
    users: fields.ReverseRelation["UserModel"]

    class Meta:
        table = "group"


class UserModel(DateTimeModel):
    uuid = fields.UUIDField(source_field="uuid", pk=True, unique=True, description="用户唯一标识")
    name = fields.CharField(source_field="username", max_length=64, description="用户展示名称,可以修改")
    password = fields.CharField(source_field="password", max_length=128, description="用户密码")
    status = fields.CharEnumField(UserStatus, default=UserStatus.OFFLINE, description="用户登录状态")
    # 一对多,关联管系,和Django没什大的区别
    group_uuid: fields.ForeignKeyRelation["GroupModel"] = \
        fields.ForeignKeyField("models.GroupModel", related_name="group", on_delete=fields.CASCADE)
    
    class Meta:
        table = "user"
        ordering = ["created_at"]

    class PydanticMeta:
        # 该字段不做展示,过滤作用
        exclude = ["password"]
    

3.数据库配置

  • 通过配置router实现读写分离
from typing import Type

from tortoise import Model


class Router:
    @staticmethod
    def db_for_read(model: Type[Model]):
        return "slave"

    @staticmethod
    def db_for_write(model: Type[Model]):
        return "master"
  • 如果数据库密码有特殊字符,需要先进性编码
import urllib.parse

urllib.parse.quote_plus("kx%jj5/g")
TORTOISE_ORM = {
    'connections': {
        'master': {
            # 'engine': 'tortoise.backends.asyncpg',  PostgreSQL 
            'engine': 'tortoise.backends.mysql',  # MySQL or Mariadb
            'credentials': {
                'host': '127.0.0.1',
                'port': '3306',
                'user': 'root',
                'password': 'password',
                'database': 'base',
                'minsize': 1,
                'maxsize': 5,
                'charset': 'utf8mb4',
                'echo': True
            }
        },
        'slave': {
            'engine': 'tortoise.backends.mysql',
            'credentials': {
                'host': '127.0.0.1',
                'port': '3306',
                'user': 'root',
                'password': 'password',
                'database': 'base',
                'minsize': 1,
                'maxsize': 5,
                'charset': 'utf8mb4',
                'echo': True
            }
        },
    },
    'apps': {
        'models': {
            'models': ['models', "aerich.models"],
            'default_connection': 'master',
        }
    },
    'routers': ["Router"],
    'use_tz': False,
    'timezone': 'Asia/Shanghai'
}

4.fastapi中引入

import uvicorn
from fastapi import FastAPI

from tortoise.contrib.fastapi import register_tortoise


app = FastAPI()


# 该方法会在fastapi启动时触发,内部通过传递进去的app对象,监听服务启动和终止事件
# 当检测到启动事件时,会初始化Tortoise对象,如果generate_schemas为True则还会进行数据库迁移
# 当检测到终止事件时,会关闭连接
register_tortoise(
    app,
    config=TORTOISE_ORM,
    # generate_schemas=True,  # 如果数据库为空,则自动生成对应表单,生产环境不要开
    # add_exception_handlers=True,  # 生产环境不要开,会泄露调试信息
)


if __name__ == '__main__':
    uvicorn.run('main:app', host='0.0.0.0', port=8000, reload=True,
                debug=True, workers=1)

5.通过aerich这个模块实现数据库的迁移,类似于django的makemigrationsmigrate功能

1.初始化配置,只需要使用一次
aerich init -t TORTOISE_ORM  # 根据自己文件实际路径写
  • 初始化完会在当前目录生成一个文件pyproject.toml和一个空文件夹migrations
    • pyproject.toml:保存配置文件路径,低版本可能是aerich.ini
    • migrations:存放迁移文件
2.初始化数据库,一般情况下只用一次
aerich init-db
  • 如果TORTOISE_ORM配置文件中的models改了名,则执行这条命令时需要增加--app参数,来指定你修改的名字
  • 生成migrstions/models文件夹
  • 生成migrstions/models/0_xxxx_init.py文件夹
3.更新模型并进行迁移
aerich migrate --name drop_column
  • 迁移文件名的格式为 {version_num}{datetime}.json。
  • 1_202029051520102929_drop_column.json
  • 如果aerich猜到您正在重命名列,它会要求重命名{old_column}为{new_column} [True],您可以选择True重命名列而不删除列,或者选择False删除列然后创建,如果使用MySQL,只有MySQL8.0+支持重命名。到语法
4.升级到最新版本
aerich upgrade
5.降级到指定版本
aerich downgrade  # 默认回退一级
  • -v:指定版本
  • -d:降级的同时删除迁移文件
  • --yes:确认删除,不再交互式输入
6.显示当前可以迁移的版本
aerich heads
7.显示迁移历史
aerich history
posted @ 2022-06-30 18:58  fatpuffer  阅读(2725)  评论(0编辑  收藏  举报