Tortoise-ORM FastAPI integration 快速入门
Tortoise-ORM FastAPI integration 快速入门
前言
初衷:在学习的时候发现 Tortoise-ORM FastAPI integration 官方文档缺中文版,翻阅英文文档效率低,萌生翻译想法。
本系列旨在原汁原味的翻译 Tortoise-ORM FastAPI integration 官方文档,帮助英语不好的小伙伴快速学习使用方法。
如果觉得翻译不错,欢迎在文章底部请博主喝杯奶茶,您的鼓励就是俺最大的动力!😄
快速上手
安装
- 首先,你需要安装 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]
除了 asyncpg
和 psycopg
之外,通过 aiosqlite
和 asyncmy
驱动程序,Tortoise-ORM 还支持 sqlite
和 asyncmy
。通过适合 asyncio
数据库驱动,您可以更轻松地实现后端。
可选加速器
以下库可用作加速器:
- orjson:如果安装了 JSON SerDes,默认自动使用。
- uvloop:已经证明可以提升性能,但需要进行一定设置。请查看
uvloop
文档获取更多信息。如果您已经使用了一种框架,它可能已经在使用了。 - ciso8601:自动使用(如果已安装)。由于 Windows 上缺少 C 编译器,因此不会自动安装。在 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
在关系数据库中,主实体(primary entity)是关系模型中的一个重要概念,它指的是在多个实体之间建立关系时,作为“主键”(primary key)的属性所在的实体。
Note: 您可以在 Models 中阅读更多有关定义模型的信息
在定义所有模型后,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 DB 数据库的连接,然后发现并初始化模型。
generate_schema
在空数据库上生成 schema
,你不应该在每个应用程序初始化时运行它,只需要在您的主代码之外运行一次。
如果在一个简单的脚本中运行,您可以这样做:
run_async(init())
run_async
是一个辅助函数,用于运行简单的异步 Tortoise 脚本。如果您在服务中运行 Tortoise ORM,请查看 The Importance of cleaning up。
在那之后,您就可以开始使用您的模型了:
# 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()
- 感谢你赐予我前进的力量