tortoies-orm 一对一、一对多和多对多关系实现
Tortoise ORM
是一个支持异步的 Python ORM(对象关系映射),主要用于与异步框架(如 FastAPI 和 Starlette)集成。它提供了简单的查询 API 来管理数据库操作,并支持常见的关系类型:一对一(OneToOne)、一对多(ForeignKey)、多对多(ManyToMany)。下面我详细讲解这些关系在 Tortoise ORM 中是如何实现的。
1. 一对一(OneToOne)
一对一的关系意味着一个表中的记录只能与另一个表中的一条记录相关联,反之亦然。Tortoise ORM 中,通过 OneToOneField
字段实现一对一关系。
示例代码:
from tortoise import Tortoise, fields
from tortoise.models import Modelclass User(Model):id = fields.IntField(pk=True)name = fields.CharField(max_length=255)profile: fields.OneToOneRelation['Profile'] = fields.OneToOneField('models.Profile', related_name='user', on_delete=fields.CASCADE)class Profile(Model):id = fields.IntField(pk=True)bio = fields.TextField()user: fields.OneToOneRelation[User] = fields.OneToOneField('models.User', related_name='profile', on_delete=fields.CASCADE)# 初始化 ORM 连接
async def init():await Tortoise.init(db_url='sqlite://:memory:', modules={'models': ['__main__']})await Tortoise.generate_schemas()# 创建记录
async def create_user_with_profile():user = await User.create(name='John')profile = await Profile.create(bio='Software Developer', user=user)# 查询数据
async def get_user_profile():user = await User.get(id=1).prefetch_related('profile')print(user.profile.bio)
说明:
OneToOneField
定义了一对一的关系。related_name
用于在关系另一侧访问该对象。on_delete=CASCADE
指定当一个User
被删除时,相关联的Profile
也会被删除。
2. 一对多(ForeignKey)
一对多的关系意味着一个表中的记录可以与另一个表中的多条记录相关联。通过 ForeignKeyField
字段来实现一对多关系。
示例代码:
class Author(Model):id = fields.IntField(pk=True)name = fields.CharField(max_length=255)books: fields.ReverseRelation['Book']class Book(Model):id = fields.IntField(pk=True)title = fields.CharField(max_length=255)author: fields.ForeignKeyRelation[Author] = fields.ForeignKeyField('models.Author', related_name='books', on_delete=fields.CASCADE)# 创建记录
async def create_author_with_books():author = await Author.create(name='J.K. Rowling')await Book.create(title='Harry Potter and the Philosopher\'s Stone', author=author)await Book.create(title='Harry Potter and the Chamber of Secrets', author=author)# 查询数据
async def get_author_books():author = await Author.get(id=1).prefetch_related('books')for book in author.books:print(book.title)
说明:
ForeignKeyField
用于定义外键字段,并将其与Author
模型关联。related_name
决定如何通过作者实例访问书籍。ReverseRelation
提供反向关系的访问,即从Author
到Book
。
3. 多对多(ManyToMany)
多对多的关系表示两个表中的记录可以相互关联,双方都可以与对方的多条记录关联。通过 ManyToManyField
字段实现多对多关系。
示例代码:
class Student(Model):id = fields.IntField(pk=True)name = fields.CharField(max_length=255)courses: fields.ManyToManyRelation['Course'] = fields.ManyToManyField('models.Course', related_name='students', through='student_course')class Course(Model):id = fields.IntField(pk=True)title = fields.CharField(max_length=255)students: fields.ManyToManyRelation[Student]# 创建记录
async def create_student_and_courses():student = await Student.create(name='Alice')course1 = await Course.create(title='Math')course2 = await Course.create(title='Science')await student.courses.add(course1, course2)# 查询数据
async def get_student_courses():student = await Student.get(id=1).prefetch_related('courses')for course in student.courses:print(course.title)
说明:
ManyToManyField
定义多对多关系,through
指定关联表的名称。related_name
决定如何通过Course
实例访问关联的Student
。add()
方法用于向多对多关系中添加对象。
总结
- 一对一关系通过
OneToOneField
实现,一个模型中的一条记录只能对应另一个模型中的一条记录。 - 一对多关系通过
ForeignKeyField
实现,一个模型中的一条记录可以对应多个关联模型的记录。 - 多对多关系通过
ManyToManyField
实现,两个模型中的记录可以相互关联多个记录。
每种关系类型都可以在查询时使用 prefetch_related
或 select_related
优化查询性能。