文章目录
- 最常用、最方便 Django 自动生成中间表 不支持自定义字段
- class Author(models.Model): name = models.CharField(max_length=100) class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField(Author)
- 方法 可用? 说明 .add(obj) ✅ 添加关联 .remove(obj) ✅ 移除关联 .set([obj1, obj2]) ✅ 重新设置关联 .clear() ✅ 清除所有关联 .all() ✅ 查询所有关联对象
- 中间模型可添加自定义字段(如创建时间、角色等) 更灵活,但略复杂
- class Author(models.Model): name = models.CharField(max_length=100) class Book(models.Model): title = models.CharField(max_length=100) authors = models.ManyToManyField( Author, through=”BookAuthor”, through_fields=(“book”, “author”) ) class BookAuthor(models.Model): book = models.ForeignKey(Book, on_delete=models.CASCADE) author = models.ForeignKey(Author, on_delete=models.CASCADE) added_at = models.DateTimeField(auto_now_add=True)
- 方法 可用? 说明 .add(obj) ❌ 被禁用,Django 不知道如何填中间表 .remove(obj) ❌ ❌ 同上 .set([obj1, obj2]) ❌ ❌ 同上 .clear() ❌ ❌ 同上 .all() ✅ 查询仍然可用
- 使用中间模型手动添加: BookAuthor.objects.create(book=book, author=author)
- 不定义 ManyToManyField 所有关系自己通过中间表查询管理 最灵活,但也最复杂,不推荐日常使用
- class Author(models.Model): name = models.CharField(max_length=100) class Book(models.Model): title = models.CharField(max_length=100) class BookAuthor(models.Model): book = models.ForeignKey(Book, on_delete=models.CASCADE) author = models.ForeignKey(Author, on_delete=models.CASCADE) added_at = models.DateTimeField(auto_now_add=True)
- 方法 可用? 说明 .add() / .remove() / 等 ❌ 没有 ManyToManyField 字段 .all() ❌ 也不能直接访问 .authors.all() 查询方式 ✅ 需手动通过中间表查询 # 查询一本书的所有作者 BookAuthor.objects.filter(book=book).select_related(“author”) # 查询一个作者的所有书 BookAuthor.objects.filter(author=author).select_related(“book”)
目录
- ✅ 方式一:默认方式(Django 自动创建中间表)
- ✅ 特点:
- ✅ 示例:
- ✅ 可用方法:
- ✅ 方式二:使用 through 自定义中间表(推荐用于需要额外字段的情况)
- ✅ 特点:
- ✅ 示例:
- ❌ 禁用方法:
- ✅ 正确操作方式:
- ✅ 方式三:完全手动中间表,无 ManyToManyField
- ✅ 特点:
- ✅ 示例:
- ❌ 所有 .authors.xxx 都不可用
- ✅ 总结对比表
- ✅ Django 多对多的 CRUD 方法汇总
- ✅ 1. C:创建关系(Create)
- ➤ 方法一:创建对象后添加关联
- ➤ 方法二:一次添加多个对象
- ✅ 2. R:查询关系(Read)
- ✅ 3. U:更新关系(Update)
- ➤ 重新设置关系(会先清空原有关系再添加新关系)
- ✅ 4. D:删除关系(Delete)
- ➤ 删除指定的某个或多个关系:
- ➤ 清除所有关系:
- ✅ 使用限制说明(重要)
- ✅ 5. 示例:完整流程演示
Django 中的多对多关系(ManyToManyField)可以通过 三种方式定义,它们在使用便捷性和可扩展性上各有差异。以下是完整总结 ✅ 并注明每种方式中哪些方法不可用:
- 最常用、最方便
- Django 自动生成中间表
- 不支持自定义字段
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
| 方法 | 可用? | 说明 |
|---|---|---|
| .add(obj) | ✅ | 添加关联 |
| .remove(obj) | ✅ | 移除关联 |
| .set([obj1, obj2]) | ✅ | 重新设置关联 |
| .clear() | ✅ | 清除所有关联 |
| .all() | ✅ | 查询所有关联对象 |
- 中间模型可添加自定义字段(如创建时间、角色等)
- 更灵活,但略复杂
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(
Author,
through="BookAuthor",
through_fields=("book", "author")
)
class BookAuthor(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
added_at = models.DateTimeField(auto_now_add=True)
| 方法 | 可用? | 说明 |
|---|---|---|
| .add(obj) | ❌ | 被禁用,Django 不知道如何填中间表 |
| .remove(obj) | ❌ | ❌ 同上 |
| .set([obj1, obj2]) | ❌ | ❌ 同上 |
| .clear() | ❌ | ❌ 同上 |
| .all() | ✅ | 查询仍然可用 |
使用中间模型手动添加:
BookAuthor.objects.create(book=book, author=author)
- 不定义
ManyToManyField
- 所有关系自己通过中间表查询管理
- 最灵活,但也最复杂,不推荐日常使用
ManyToManyField
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
class BookAuthor(models.Model):
book = models.ForeignKey(Book, on_delete=models.CASCADE)
author = models.ForeignKey(Author, on_delete=models.CASCADE)
added_at = models.DateTimeField(auto_now_add=True)
| 方法 | 可用? | 说明 |
|---|---|---|
| .add() / .remove() / 等 | ❌ | 没有 ManyToManyField 字段 |
| .all() | ❌ | 也不能直接访问 .authors.all() |
| 查询方式 | ✅ | 需手动通过中间表查询 |
# 查询一本书的所有作者
BookAuthor.objects.filter(book=book).select_related("author")
# 查询一个作者的所有书
BookAuthor.objects.filter(author=author).select_related("book")
| 方式 | 是否有中间模型 | 是否能添加中间字段 | 快捷方法(add/remove/set) | 推荐用途 |
|---|---|---|---|---|
| 默认 ManyToManyField | ❌(Django 自动) | ❌ | ✅ 可用 | 简单多对多关系 |
| ManyToManyField + through | ✅ | ✅ | ❌ 被禁用 | 多对多且需附加字段场景 |
| 完全手动中间模型 | ✅ | ✅ | ❌ 全部禁用 | 高度自定义业务、底层控制场景 |
在 Django 中,ManyToManyField 提供了一套专门用于 增删改查(CRUD) 的方法,用于操作模型之间的多对多关系。以下是完整的 CRUD 方法总结(适用于未使用 through 中间模型的情况):
假设模型如下:
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField(Author)
book = Book.objects.create(title="Python入门")
author = Author.objects.create(name="张三")
book.authors.add(author) # 添加关联关系
book.authors.add(author1, author2, author3)
# 查询某本书的所有作者
book.authors.all()
# 查询某个作者参与的所有书(反向查询)
author.book_set.all()
# 如果设置了 related_name="books",可以用:
author.books.all()
book.authors.set([author1, author2]) # 只保留这两个作者
book.authors.remove(author1)
book.authors.remove(author1, author2)
book.authors.clear()
| 方法 | 是否可用 | 条件说明 |
|---|---|---|
| .add() | ✅ | 不能用于通过 through 自定义中间模型 |
| .remove() | ✅ | 同上 |
| .clear() | ✅ | 同上 |
| .set() | ✅ | 同上 |
| .all() | ✅ | 始终可用 |
❗ 如果你在 ManyToManyField 中使用了 through="XXX",上述 .add() 等方法会全部失效,必须手动操作中间模型。
# 添加关系
book = Book.objects.create(title="FastAPI进阶")
author1 = Author.objects.create(name="Alice")
author2 = Author.objects.create(name="Bob")
book.authors.add(author1, author2)
# 查询关系
for author in book.authors.all():
print(author.name)
# 更新关系
book.authors.set([author2]) # 现在只有 Bob
# 删除单个关系
book.authors.remove(author2)
# 清空所有关系
book.authors.clear()
到此这篇关于Django中多对多关系三种定义方式的文章就介绍到这了,更多相关Django 多对多关系创建内容请搜索风君子博客以前的文章或继续浏览下面的相关文章希望大家以后多多支持风君子博客!
您可能感兴趣的文章:
- django ManyToManyField多对多关系的实例详解
- django数据关系一对多、多对多模型、自关联的建立
- Django之多对多查询与操作方法详解
- Django 多对多字段的更新和插入数据实例
- Django中数据库的数据关系:一对一,一对多,多对多
- 基于Django ORM、一对一、一对多、多对多的全面讲解
- Django 标签筛选的实现代码(一对多、多对多)
- django 多对多表的创建和插入代码实现
- Django Xadmin多对多字段过滤实例