如何在Django多对多关系中获取有书籍的不重复Genre对象?
获取关联书籍的不重复流派列表
针对你给出的Django模型,这里有几种简单高效的方式来获取所有至少关联了一本书籍的流派,并且保证列表里没有重复项:
方法1:使用exists子查询(推荐)
这是性能最优的写法,因为它会生成数据库层面的EXISTS查询,避免不必要的数据加载:
genres_with_books = Genre.objects.filter(book__exists=True)
book__exists=True会筛选出所有被至少一本Book关联的Genre对象,天然不会有重复(因为我们直接查询的是Genre表,每个对象唯一)。
方法2:过滤非空关联并去重
如果习惯更直观的写法,也可以用isnull=False配合distinct():
genres_with_books = Genre.objects.filter(book__isnull=False).distinct()
这里book__isnull=False确保流派有对应的书籍,distinct()用来避免因为多对多关联导致的重复查询结果(不过在大多数情况下,直接查询Genre表的话,distinct()其实可以省略,加上更稳妥)。
方法3:从书籍反向获取流派ID
如果需要从Book模型入手,也可以通过书籍的关联ID来筛选流派:
# 先获取所有关联过流派的书籍的流派ID,再筛选对应的Genre genre_ids = Book.objects.values_list('genre__pk', flat=True).distinct() genres_with_books = Genre.objects.filter(pk__in=genre_ids)
在视图和模板中使用
比如在视图里传递这个列表到模板:
from django.shortcuts import render from .models import Genre def book_genres(request): genres = Genre.objects.filter(book__exists=True) return render(request, 'your_template.html', {'genres': genres})
模板里遍历展示:
<h3>有书籍的流派列表</h3> <ul> {% for genre in genres %} <li>{{ genre.name }}</li> {% empty %} <li>暂无关联书籍的流派</li> {% endfor %} </ul>
这些方法都能完美满足你的需求:拿到所有对应有书籍的流派,且列表无重复项。
内容的提问来源于stack exchange,提问作者Tuhin
相关产品推荐
相关产品推荐

