fastapi框架tortoise-orm运用

巴洲
2023-12-01

创建数据库连接

from fastapi import FastAPI
from tortoise.contrib.fastapi import register_tortoise

from app.config import config


class GetDB(object):

    def _get_orm_base_conf(self, apps: dict) -> dict:
        return {
            'connections': {
                'default': {
                    'engine': 'tortoise.backends.mysql',
                    'credentials': {
                        'host': config.MYSQL_HOST,
                        'port': config.MYSQL_PORT,
                        'user': config.MYSQL_USERNAME,
                        'password': config.MYSQL_PASSWORD,
                        'database': config.MYSQL_DATABASE,
                        'minsize': 1,
                        'maxsize': 5,
                        'charset': 'utf8mb4'
                    }
                }
            },
            'apps': apps,
            'use_tz': False,
            'timezone': 'Asia/Shanghai'
        }

    @property
    def orm_link_conf(self) -> dict:
        orm_apps_settings = {
            'models': {
                'models': [
                    'app.models.__init__'
                ],
                'default_connection': 'default',
            },
        }
        return self._get_orm_base_conf(orm_apps_settings)


ORM_LINK_CONF = GetDB().orm_link_conf


def init_db(app: FastAPI):
    """init and bind tortoise-orm"""
    register_tortoise(
        app,
        config=ORM_LINK_CONF
    )

GetDB类的属性方法orm_link_conf中 models表示是自己的数据库model的项目地址。fastapi 中创建app对象的时候,将 init_db 方法绑定到app:

def create_app():
    app = FastAPI(
        debug=True,
        title=config.TITLE,
        description="",
        version=config.VERSION,
        docs_url=config.DOCS_URL,
        openapi_url=config.OPENAPI_URL,
        redoc_url=None,
        openapi_tags=tag_metadata,
    )

    app.include_router(
        api_router,
        prefix=config.API_PREFIX,
    )
    init_db(app)  # 绑定数据库
    register_exception(app)  # 注册捕获异常信息
    register_cors(app)  # 跨域设置
    register_middleware(app)
    return app

数据库操作

数据库model, 以Role为例

class Role(Model):
    """权限-角色"""
    name = fields.CharField(max_length=200, unique=True, description="角色名", default='')
    permission = fields.ManyToManyField("models.Permission", related_name='related_permission_role',
                                        description="权限-角色关联权限")
    addtime = fields.DatetimeField(description="添加时间", default=datetime.datetime.now())

1.插入

await Role.create(name="审计员")

也可以写成

await Role.create(**dict(name="管理员"))

2.更新

await Role.filter(pk=1).update(**dict(name="管理员"))
role = await Role.filter(pk=1).first()
role.name = "管理员"
await role.save()

1.删除

await Role.filter(pk=1).delete()
role = await Role.filter(pk=1).first()
await role.delete()

1.查询

1.查询所有

roles = await Role.filter().all()

2.查询单条记录

roles = await Role.filter().first()

3.记录是否存在

await Role.filter(name='管理员').exists()

4.将查询的结果转换为列表

roles = await Role.filter().all().values()

5.查询条件
not
in- 检查字段的值是否位于传递列表中
not_in
gte- 大于或等于传递的值
gt- 大于传递的值
lte- 低于或等于传递的值
lt- 低于传递值
range- 介于和给定两个值之间
isnull- 字段为空
not_isnull- 字段不为空
contains- 字段包含指定的子字符串
icontains- 不区分大小写contains
startswith- 如果字段以值开头
istartswith- 不区分大小写startswith
endswith- 如果字段以值结尾
iendswith- 不区分大小写endswith
iequals- 区分大小写等于

roles = await Role.filter(name__icontains="abc").all()

6.group by , order by, sum, count , limit, offset 等

roles = await Role.filter().annotate(count=Count("id")).group_by("name").limit(10).offset(10).values()

order_by如果需要排序的话可以直接排序

根据id 升序排列
order_by("id")
根据id降序排列
order_by("-id")

7.对时间进行格式化

from pypika import CustomFunction
class TruncMonth(Function):
        database_func = CustomFunction("DATE_FORMAT", ["name", "dt_format"])
 
roles = await Role.filter().annotate(date=TruncMonth('addtime', '%Y-%m-%d'), count=Count("id")).group_by("date").values("date", "count")

注意 时间格式化 对应的 tortoise-orm 版本要 0.17以上 0.16.16 会报错

 类似资料: