入门

安装

首先,您必须像这样安装 tortoise

pip install tortoise-orm

您还可以使用您的数据库驱动程序进行安装

pip install tortoise-orm[asyncpg]

或 PsycoPG

pip install tortoise-orm[psycopg]

对于 MySQL

pip install tortoise-orm[asyncmy]

对于 Microsoft SQL Server/Oracle

pip install tortoise-orm[asyncodbc]

除了 asyncpgpsycopg 之外,还支持通过 aiosqlite 使用 sqlite,以及通过 asyncmy 使用 mysql。如果为此数据库有合适的 asyncio 驱动程序,您可以轻松地实现更多后端。

可选加速器

以下库可用作加速器

  • orjson:如果已安装,则自动用于 JSON SerDes。

  • uvloop:已显示可以提高性能,但需要进行设置。请参阅 uvloop 文档了解更多信息。如果您使用框架,它可能已经使用了它。

  • ciso8601:如果已安装,则自动使用。由于经常缺少 C 编译器,因此不会自动安装在 Windows 上。Linux/CPython 上的默认设置。

您可以使用上述所有加速器进行安装

pip install tortoise-orm[accel]

教程

tortoise 的主要实体是 tortoise.models.Model。您可以像这样开始编写模型

from tortoise.models import Model
from tortoise import fields

class Tournament(Model):
    # Defining `id` field is optional, it will be defined automatically
    # if you haven't done it yourself
    id = fields.IntField(primary_key=True)
    name = fields.CharField(max_length=255)

    # Defining ``__str__`` is also optional, but gives you pretty
    # represent of model in debugger and interpreter
    def __str__(self):
        return self.name


class Event(Model):
    id = fields.IntField(primary_key=True)
    name = fields.CharField(max_length=255)
    # References to other models are defined in format
    # "{app_name}.{model_name}" - where {app_name} is defined in tortoise config
    tournament = fields.ForeignKeyField('models.Tournament', related_name='events')
    participants = fields.ManyToManyField('models.Team', related_name='events', through='event_team')

    def __str__(self):
        return self.name


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

    def __str__(self):
        return self.name

注意

您可以在 模型 中阅读有关定义模型的更多信息

在您定义完所有模型后,tortoise 需要您初始化它们,以便在模型之间创建反向关系,并将您的数据库客户端与适当的模型匹配。

您可以像这样执行此操作

from tortoise import Tortoise

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()

在此,我们使用默认 aiosqlite 客户端创建到 SQLite 数据库的连接,然后我们发现并初始化模型。

generate_schema 在空数据库上生成模式,您不应该在每次应用程序初始化时运行它,只运行一次,可能在您的主代码之外。

如果您在简单脚本中运行此脚本,则可以执行

run_async(init())

run_async 是运行简单异步 Tortoise 脚本的辅助函数。如果您将 Tortoise ORM 作为服务的一部分运行,请参阅 清理的重要性

之后,您可以开始使用您的模型

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

# Or by .create()
await Event.create(name='Without participants', tournament=tournament)
event = await Event.create(name='Test', tournament=tournament)
participants = []
for i in range(2):
    team = await Team.create(name='Team {}'.format(i + 1))
    participants.append(team)

# M2M Relationship management is quite straightforward
# (look for methods .remove(...) and .clear())
await event.participants.add(*participants)

# You can query related entity just with async for
async for team in event.participants:
    pass

# After making related query you can iterate with regular for,
# which can be extremely convenient for using with other packages,
# for example some kind of serializers with nested support
for team in event.participants:
    pass


# Or you can make preemptive call to fetch related objects,
# so you can work with related objects immediately
selected_events = await Event.filter(
    participants=participants[0].id
).prefetch_related('participants', 'tournament')
for event in selected_events:
    print(event.tournament.name)
    print([t.name for t in event.participants])

# Tortoise ORM supports variable depth of prefetching related entities
# This will fetch all events for team and in those team tournament will be prefetched
await Team.all().prefetch_related('events__tournament')

# You can filter and order by related models too
await Tournament.filter(
    events__name__in=['Test', 'Prod']
).order_by('-events__participants__name').distinct()

注意

您可以在 示例 中阅读更多示例(包括事务、多个数据库和稍微复杂一些的查询)