基于官方的示例模型
from tortoise import Tortoise, fields, run_async
from tortoise.contrib.pydantic import pydantic_model_creator, pydantic_queryset_creator
from tortoise.models import Model
class Tournament(Model):
id = fields.IntField(pk=True)
name = fields.TextField()
created_at = fields.DatetimeField(auto_now_add=True)
events: fields.ReverseRelation["Event"]
class Meta:
ordering = ["name"]
class Event(Model):
id = fields.IntField(pk=True)
name = fields.TextField()
created_at = fields.DatetimeField(auto_now_add=True)
tournament: fields.ForeignKeyNullableRelation["Tournament"] = fields.ForeignKeyField(
"models.Tournament", related_name="events", null=True
)
participants: fields.ManyToManyRelation["Team"] = fields.ManyToManyField(
"models.Team", related_name="events", through="event_team"
)
address: fields.OneToOneNullableRelation["Address"]
class Meta:
ordering = ["name"]
class Address(Model):
city = fields.CharField(max_length=64)
street = fields.CharField(max_length=128)
created_at = fields.DatetimeField(auto_now_add=True)
event: fields.OneToOneRelation["Event"] = fields.OneToOneField(
"models.Event", on_delete=fields.OnDelete.CASCADE, related_name="address", pk=True
)
class Meta:
ordering = ["city"]
class Team(Model):
id = fields.IntField(pk=True)
name = fields.TextField()
created_at = fields.DatetimeField(auto_now_add=True)
events: fields.ManyToManyRelation["Event"]
class Meta:
ordering = ["name"]
1. 模型关联的定义
# 原始:
participants: fields.ManyToManyRelation[Team]
# 修改为:
participants: fields.ManyToManyRelation["Team"]
# 这样和其它模型定义关联保持一致,更容易理解
2. 关于示例模型的理解
官方示例很说明问题,其中涵盖了基本的表结构定义模式,已经双向引用的模式定义,具体使用方式参考官文就可以
3. 使用ORM模块提供的Pydantic数据抽象模块
后续的例子会提供,从网上看到大多数教程大都自定义映射,繁琐且容易出错
4. 生成的数据表
通过创建的表和表结构,ORM为我们创建好了各种表和对应的关
模型测试
async def run():
await Tortoise.init(db_url="sqlite://:memory:", modules={"models": ["__main__"]})
await Tortoise.generate_schemas()
Event_Pydantic = pydantic_model_creator(Event)
Event_Pydantic_List = pydantic_queryset_creator(Event)
Tournament_Pydantic = pydantic_model_creator(Tournament)
Team_Pydantic = pydantic_model_creator(Team)
Address_Pydantic = pydantic_model_creator(Address)
tournament = await Tournament.create(name="New Tournament")
tournament2 = await Tournament.create(name="Old Tournament")
await Event.create(name="Empty")
event = await Event.create(name="Test", tournament=tournament)
event2 = await Event.create(name="TestLast", tournament=tournament)
event3 = await Event.create(name="Test2", tournament=tournament2)
await Address.create(city="Santa Monica", street="Ocean", event=event)
await Address.create(city="Beijing", street="G6", event=event2)
team1 = await Team.create(name="Onesies")
team2 = await Team.create(name="T-Shirts")
team3 = await Team.create(name="Alternates")
await event.participants.add(team1, team2, team3)
await event2.participants.add(team1, team2)
await event3.participants.add(team1, team3)
p = await Event_Pydantic.from_tortoise_orm(await Event.get(name="Test"))
print("基于Event 'One Event:' \n", p.model_dump_json(indent=4))
p = await Address_Pydantic.from_tortoise_orm(await Address.all().first())
print("基于Address 'One Address:' \n", p.model_dump_json(indent=4))
#
p = await Tournament_Pydantic.from_tortoise_orm(await Tournament.get(name="New Tournament"))
print("基于 Tournament 'One Tournament:'\n", p.model_dump_json(indent=4))
#
p = await Team_Pydantic.from_tortoise_orm(await Team.get(name="Onesies"))
print("基于 Team 'One Team:' \n", p.model_dump_json(indent=4))
#
pl = await Event_Pydantic_List.from_queryset(Event.filter(address__event_id__isnull=True))
print("All Events without addresses: \n", pl.model_dump_json(indent=4))
if __name__ == "__main__":
run_async(run())
执行结果
基于Event 'One Event:'
{
"id": 2,
"name": "Test",
"created_at": "2024-01-18T07:25:49.256352Z",
"tournament": {
"id": 1,
"name": "New Tournament",
"created_at": "2024-01-18T07:25:49.255311Z"
},
"participants": [
{
"id": 3,
"name": "Alternates",
"created_at": "2024-01-18T07:25:49.259313Z"
},
{
"id": 1,
"name": "Onesies",
"created_at": "2024-01-18T07:25:49.258312Z"
},
{
"id": 2,
"name": "T-Shirts",
"created_at": "2024-01-18T07:25:49.259313Z"
}
],
"address": {
"city": "Santa Monica",
"street": "Ocean",
"created_at": "2024-01-18T07:25:49.258312Z",
"event_id": 2
}
}
基于Address 'One Address:'
{
"city": "Beijing",
"street": "G6",
"created_at": "2024-01-18T07:25:49.258312Z",
"event": {
"id": 3,
"name": "TestLast",
"created_at": "2024-01-18T07:25:49.257311Z",
"tournament": {
"id": 1,
"name": "New Tournament",
"created_at": "2024-01-18T07:25:49.255311Z"
},
"participants": [
{
"id": 1,
"name": "Onesies",
"created_at": "2024-01-18T07:25:49.258312Z"
},
{
"id": 2,
"name": "T-Shirts",
"created_at": "2024-01-18T07:25:49.259313Z"
}
]
},
"event_id": 3
}
基于 Tournament 'One Tournament:'
{
"id": 1,
"name": "New Tournament",
"created_at": "2024-01-18T07:25:49.255311Z",
"events": [
{
"id": 2,
"name": "Test",
"created_at": "2024-01-18T07:25:49.256352Z",
"participants": [
{
"id": 3,
"name": "Alternates",
"created_at": "2024-01-18T07:25:49.259313Z"
},
{
"id": 1,
"name": "Onesies",
"created_at": "2024-01-18T07:25:49.258312Z"
},
{
"id": 2,
"name": "T-Shirts",
"created_at": "2024-01-18T07:25:49.259313Z"
}
],
"address": {
"city": "Santa Monica",
"street": "Ocean",
"created_at": "2024-01-18T07:25:49.258312Z",
"event_id": 2
}
},
{
"id": 3,
"name": "TestLast",
"created_at": "2024-01-18T07:25:49.257311Z",
"participants": [
{
"id": 1,
"name": "Onesies",
"created_at": "2024-01-18T07:25:49.258312Z"
},
{
"id": 2,
"name": "T-Shirts",
"created_at": "2024-01-18T07:25:49.259313Z"
}
],
"address": {
"city": "Beijing",
"street": "G6",
"created_at": "2024-01-18T07:25:49.258312Z",
"event_id": 3
}
}
]
}
基于 Team 'One Team:'
{
"id": 1,
"name": "Onesies",
"created_at": "2024-01-18T07:25:49.258312Z",
"events": [
{
"id": 2,
"name": "Test",
"created_at": "2024-01-18T07:25:49.256352Z",
"tournament": {
"id": 1,
"name": "New Tournament",
"created_at": "2024-01-18T07:25:49.255311Z"
},
"address": {
"city": "Santa Monica",
"street": "Ocean",
"created_at": "2024-01-18T07:25:49.258312Z",
"event_id": 2
}
},
{
"id": 4,
"name": "Test2",
"created_at": "2024-01-18T07:25:49.257311Z",
"tournament": {
"id": 2,
"name": "Old Tournament",
"created_at": "2024-01-18T07:25:49.255311Z"
},
"address": null
},
{
"id": 3,
"name": "TestLast",
"created_at": "2024-01-18T07:25:49.257311Z",
"tournament": {
"id": 1,
"name": "New Tournament",
"created_at": "2024-01-18T07:25:49.255311Z"
},
"address": {
"city": "Beijing",
"street": "G6",
"created_at": "2024-01-18T07:25:49.258312Z",
"event_id": 3
}
}
]
}
All Events without addresses:
[
{
"id": 1,
"name": "Empty",
"created_at": "2024-01-18T07:25:49.256352Z",
"tournament": null,
"participants": [],
"address": null
},
{
"id": 4,
"name": "Test2",
"created_at": "2024-01-18T07:25:49.257311Z",
"tournament": {
"id": 2,
"name": "Old Tournament",
"created_at": "2024-01-18T07:25:49.255311Z"
},
"participants": [
{
"id": 3,
"name": "Alternates",
"created_at": "2024-01-18T07:25:49.259313Z"
},
{
"id": 1,
"name": "Onesies",
"created_at": "2024-01-18T07:25:49.258312Z"
}
],
"address": null
}
]