本文介绍: 当您构建使用关系数据库应用程序服务时,有时您不能仅仅使用参数查询甚至查询构建器就可以逃脱,您只是不断重复自己,为每个实体编写略有不同代码代码知道数据之间关系,因此您最终几乎是手动连接数据访问数据库方式也很容易出错,从而很容易发生 SQL 注入攻击。您的数据规则也是分布式的,增加了管理数据复杂性,更糟糕的是,应用不一致。ORM(对象关系映射器)旨在解决这些问题通过集中您的数据模型和数据规则,确保您的数据得到安全管理(提供对 SQL 注入的免疫力)并跟踪关系,因此您不必。

Tortoise ORM

一、 简介

1、 ORM

当您构建使用关系数据库应用程序服务时,有时您不能仅仅使用参数查询甚至查询构建器就可以逃脱,您只是不断重复自己,为每个实体编写略有不同代码代码知道数据之间的关系,因此您最终几乎是手动连接数据。访问数据库方式也很容易出错,从而很容易发生 SQL 注入攻击。您的数据规则也是分布式的,增加了管理数据的复杂性,更糟糕的是,应用不一致。

ORM(对象关系映射器)旨在解决这些问题通过集中您的数据模型和数据规则,确保您的数据得到安全管理(提供对 SQL 注入的免疫力)并跟踪关系,因此您不必。

2、 介绍

Tortoise ORM 是受 Django 启发的易于使用asyncioORM 对象关系映射器)

Tortoise ORM 的构建类似于 Django ORM。它的设计中不仅使用表格,还使用关系数据。

与其他 Python ORM 相比,它也表现良好,与 Pony ORM 进行交易

Django ORM 语法

SQLAlchemy 语法

官方文档地址https://tortoise-orm.readthedocs.io/en/latest/index.html

3、 简单使用

创建模型

from tortoise.models import Model
from tortoise import fields

class Tournament(Model):
    id = fields.IntField(pk=True)
    name = fields.TextField()

创建表,初始化数据库

from tortoise import Tortoise, run_async

async def init():
    # Here we create a SQLite DB using file "db.sqlite3"
    #  also specify the app name of "models"
    #  which contain models from "app.models"
    await Tortoise.init(
        db_url='sqlite://db.sqlite3',
        modules={'models': ['app.models']}
    )
    # Generate the schema
    await Tortoise.generate_schemas()

# run_async is a helper function to run simple async Tortoise scripts.
run_async(init())

数据查询:

# Create instance by save
tournament = Tournament(name='New Tournament')
await tournament.save()

# Or by .create()
await Tournament.create(name='Another Tournament')

# Now search for a record
tour = await Tournament.filter(name__contains='Another').first()
print(tour.name)

4、 环境配置

pip install tortoise-orm

# 安装数据库驱动
pip install tortoise-orm[asyncpg]
pip install tortoise-orm[aiomysql]
pip install tortoise-orm[asyncmy]
# 除此之外,还支持:aiosqlite

二、 基础配置

1、 数据库链接

Tortoise 目前支持以下数据库

要使用,请确保已安装asyncpg和/或aiomysql

Tortoise 支持以 URL 形式指定数据库配置:

语法

  • DB_TYPE://USERNAME:PASSWORD@HOST:PORT/DB_NAME?PARAM1=value&PARAM2=value

支持的DB_TYPE

更详细的可以进入官方文档查看https://tortoise-orm.readthedocs.io/en/latest/databases.html

2、 创建数据库

from tortoise import Tortoise, run_async

async def init():
    # Here we create a SQLite DB using file "db.sqlite3"
    #  also specify the app name of "models"
    #  which contain models from "app.models"
    await Tortoise.init(
        db_url='sqlite://db.sqlite3',
        modules={'models': ['app.models']}
    )
    # Generate the schema
    await Tortoise.generate_schemas()  # safe:仅在表不存在创建

run_async(init())  # 会自动进入上下文处理,在运行完成时,自动关闭数据库连接

三、 模型

1、 创建

from tortoise.models import Model

class Tournament(Model):
    id = fields.IntField(pk=True)
    name = fields.TextField()
    created = fields.DatetimeField(auto_now_add=True)

    def __str__(self):
        return self.name


class Event(Model):
    id = fields.IntField(pk=True)
    name = fields.TextField()
    tournament = fields.ForeignKeyField('models.Tournament', related_name='events')
    participants = fields.ManyToManyField('models.Team', related_name='events', through='event_team')
    modified = fields.DatetimeField(auto_now=True)
    prize = fields.DecimalField(max_digits=10, decimal_places=2, null=True)

    def __str__(self):
        return self.name


class Team(Model):
    id = fields.IntField(pk=True)
    name = fields.TextField()

     class Meta:
        abstract = True  # 设置为True表明这是一个抽象类
        table = "team"  # 设置表名
        table_description = ""  # 设置此项可为为当前模型创建的表生成注释消息
		unique_together = ()  # 指定unique_together为列集设置复合唯一索引,其为元组的元组(列表很好)
        indexes = ()  # 指定indexes为列集设置复合唯一索引,它应该是元组的元组(列表很好)
		ordering = []  # 指定ordering为给定模型设置默认排序。.order_by(...)它应该可以迭代以与接收相同方式格式化字符串。如果查询是GROUP_BY使用默认排序子句构建的,.annotate(...)则不应用

		manager = tortoise.manager.Manager  # 指定manager覆盖默认管理器。它应该是实例tortoise.manager.Manager或子类

2、 多表关联

from tortoise.models import Model
from tortoise import fields


class Tournament(Model):
    id = fields.IntField(pk=True)
    name = fields.CharField(max_length=255)

    events: fields.ReverseRelation["Event"]

    def __str__(self):
        return self.name


class Event(Model):
    id = fields.IntField(pk=True)
    name = fields.CharField(max_length=255)
    tournament: fields.ForeignKeyRelation[Tournament] = fields.ForeignKeyField(
        "models.Tournament", related_name="events"
    )
    participants: fields.ManyToManyRelation["Team"] = fields.ManyToManyField(
        "models.Team", related_name="events", through="event_team"
    )

    def __str__(self):
        return self.name


class Team(Model):
    id = fields.IntField(pk=True)
    name = fields.CharField(max_length=255)

    events: fields.ManyToManyRelation[Event]

    def __str__(self):
        return self.name

3、 字段

更详细的信息可以查看官方文档https://tortoise-orm.readthedocs.io/en/latest/fields.html

3.1 数据字段

Field(source_field = None , generated = False , pk = False , null = False , default = None , unique = False , index = False , description = None , model = None , validators = None , ** kwargs

参数

3.2 关系字段

ForeignKeyField( model_name , related_name = None , on_delete = 'CASCADE' , db_constraint = True , ** kwargs )

参数

ManyToManyField(model_name, through=None, forward_key=None, backward_key='', related_name='', on_delete='CASCADE', db_constraint=True, **kwargs)

参数:

OneToOneField( model_name , related_name = None , on_delete = 'CASCADE' , db_constraint = True , ** kwargs )

这些参数在上面两个字段中全部都解释了,就不再进行解释

4、 查询

4.1 基础

模型本身有几种方法可以启动查询:

模型类也有这个方法创建对象

模型本身的实例也有这些方法

values()  # 返回queryset里面字段的值
values_list()  # 返回queryset里面字段的值,同时,内部可以指定需要返回的字段的值

events = await Event.filter(id__in=[1,2,3]).values('id', 'name', tournament_name='tournament__name')  # 比如

使用values()values_list()生成更有效的查询

filter可以指定的对象

使用示例

from tortoise.functions import Count, Trim, Lower, Upper, Coalesce

# This query will fetch all tournaments with 10 or more events, and will
# populate filed `.events_count` on instances with corresponding value
await Tournament.annotate(events_count=Count('events')).filter(events_count__gte=10)
await Tournament.annotate(clean_name=Trim('name')).filter(clean_name='tournament')
await Tournament.annotate(name_upper=Upper('name')).filter(name_upper='TOURNAMENT')
await Tournament.annotate(name_lower=Lower('name')).filter(name_lower='tournament')
await Tournament.annotate(desc_clean=Coalesce('desc', '')).filter(desc_clean='')

同时,对于一对多和多对多,可以直接使用那个字段名行数据的操作

4.2 Q 对象

Q 对象非常通用,一些示例用例

比如

Q( * args , join_type = 'AND' , ** kwargs )

参数:

found_events = await Event.filter(
    Q(Q(name='Event 1'), Q(name='Event 2'), join_type="OR")  # Q(name='Event 1') | Q(name='Event 2')
)
4.3 F 表达式

F对象表示模型字段的值。它可以引用模型字段值并使用它们执行数据库操作,而无需将它们从数据库中拉出到 Python 内存

from tortoise.expressions import F
await User.filter(id=1).update(balance = F('balance') - 10)
await User.filter(id=1).update(balance = F('balance') + F('award'), award = 0)

# or use .save()
user = await User.get(id=1)
user.balance = F('balance') - 10
await user.save(update_fields=['balance'])

五、 迁移

我们使用Aerich进行迁移https://github.com/tortoise/aerich

安装:pip install aerich

aerich -h

Usage: aerich [OPTIONS] COMMAND [ARGS]...

Options:
  -c, --config TEXT  Config file.  [default: aerich.ini]
  --app TEXT         Tortoise-ORM app name.  [default: models]
  -n, --name TEXT    Name of section in .ini file to use for aerich config.
                     [default: aerich]
  -h, --help         Show this message and exit.

Commands:
  downgrade  Downgrade to specified version.
  heads      Show current available heads in migrate location.
  history    List all migrate items.
  init       Init config file and generate root migrate location.
  init-db    Generate schema and generate app migrate location.
  migrate    Generate migrate changes file.
  upgrade    Upgrade to latest version.

用法

您需要先将 aerich.models添加到您的Tortoise-ORM配置中

TORTOISE_ORM = {
    "connections": {"default": "mysql://root:123456@127.0.0.1:3306/test"},
    "apps": {
        "models": {
            "models": ["tests.models", "aerich.models"],  
            "default_connection": "default",
        },
    },
}

初始化配置文件和设置:

aerich init -t tests.backends.mysql.TORTOISE_ORM

数据库进行操作

aerich init-db  # 初始化数据库
aerich migrate --name drop_column  # 更新并进行迁移
aerich upgrade  # 升级数据库
aerich downgrade  # 降级数据库到某个版本
aerich history  # 显示迁移历史
aerich heads  # 显示迁移的磁头

这里部分是理论知识例子可以自行到官方文档查看https://tortoise-orm.readthedocs.io/en/latest/examples/

原文地址:https://blog.csdn.net/qq_62789540/article/details/127251395

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_32016.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注