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"]
# 原始:
participants: fields.ManyToManyRelation[Team]
# 修改为:
participants: fields.ManyToManyRelation["Team"]
# 这样和其它模型定义关联保持一致,更容易理解
官方示例很说明问题,其中涵盖了基本的表结构定义模式,已经双向引用的模式定义,具体使用方式参考官文就可以
后续的例子会提供,从网上看到大多数教程大都自定义映射,繁琐且容易出错
通过创建的表和表结构,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
? ? }
]
?