如何在Django中查询Author与Post的多对多关联关系
Django多对多关联查询获取完整关联结果表
模型定义
# models.py class Author(models.Model): name = models.CharField(max_length=200) email = models.EmailField() class Post(models.Model): authors = models.ManyToManyField(Author) headline = models.CharField(max_length=255) body_text = models.TextField(null=True, blank=True)
现有数据
Author表
| author_id | name | |
|---|---|---|
| 1 | John Doe | jdoe@test.com |
| 2 | Peter Smith | psmith@test.com |
| 3 | Karen Jackson | kjackson@test.com |
Post表
| post_id | headline | body |
|---|---|---|
| 1 | Worpress tutorial | Lorem Ipsum is simply dummy text... |
| 2 | Developer news | Lorem Ipsum is simply dummy text... |
| 3 | Science news | Lorem Ipsum is simply dummy text... |
期望结果表
| autor_post_id | author_id | name | post_id | headline | body | |
|---|---|---|---|---|---|---|
| 1 | 1 | John Doe | jdoe@test.com | 1 | Worpress tutorial | Lorem... |
| 2 | 2 | Peter Smith | psmith@test.com | 1 | Worpress tutorial | Lorem... |
| 3 | 1 | John Doe | jdoe@test.com | 2 | Developer news | Lorem... |
| 4 | 2 | Peter Smith | psmith@test.com | 2 | Developer news | Lorem... |
| 5 | 3 | Karen Jackson | kjackson@test.com | 3 | Science news | Lorem... |
| 6 | 1 | John Doe | jdoe@test.com | 3 | Science news | Lorem... |
查询方案
方案1:使用Django ORM 推荐
Django会自动为多对多关系生成中间表,我们可以通过Post.authors.through直接获取该中间表模型,再关联Author和Post表查询所需字段:
from yourapp.models import Post # 获取多对多关联的中间表模型 PostAuthor = Post.authors.through # 执行关联查询,预加载关联对象避免N+1查询,指定所需字段并排序 queryset = PostAuthor.objects.select_related('author', 'post').values( 'id', # 对应结果表的autor_post_id 'author_id', 'author__name', 'author__email', 'post_id', 'post__headline', 'post__body_text' ).order_by('id') # 遍历结果,每个元素是包含所有字段的字典 for item in queryset: print(item)
方案2:使用原生SQL查询
如果需要直接编写SQL语句,执行以下代码(注意替换yourapp为你的实际应用名称):
SELECT pa.id AS autor_post_id, pa.author_id, a.name, a.email, pa.post_id, p.headline, p.body_text AS body FROM yourapp_post_authors pa INNER JOIN yourapp_author a ON pa.author_id = a.id INNER JOIN yourapp_post p ON pa.post_id = p.id ORDER BY pa.id;
说明
- ORM方式无需硬编码表名,更符合Django开发规范,且能自动适配不同数据库。
- ORM返回的
QuerySet支持链式调用filter()、annotate()等方法,方便后续数据处理。
内容的提问来源于stack exchange,提问作者Oile Nosreg
相关产品推荐
相关产品推荐

