You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何查询拥有至少一本关联书籍的Author对象?分页异常求助

解决Django获取拥有至少一本图书的作者查询集问题

之前你用Author.objects.all()拿全量作者,再在模板里判断是否有图书的做法,会导致两个核心问题:

  • 分页逻辑混乱:分页是按全量作者数量计算的,但实际只显示有书的作者,比如每页设10个,可能实际页面只显示5个,分页导航和实际内容完全不匹配
  • 性能浪费:每个作者都要额外查一次关联的图书,产生N+1查询,数据量越大性能越差

直接在数据库层面过滤出至少拥有一本图书的作者,就能彻底解决这些问题,下面是两种常用实现方式:

方法一:排除无关联图书的作者

利用Django ORM的反向关联查询,直接排除掉没有绑定Book的作者:

# 视图中获取过滤后的查询集
authors_with_books = Author.objects.exclude(book__isnull=True)

这个查询会生成对应的SQL语句,在数据库层面完成过滤,返回的结果就是所有有书的作者集合。

方法二:统计图书数量并过滤

如果后续需要显示每个作者的图书数量,可以用annotate配合Count做统计,再过滤出数量大于0的作者:

from django.db.models import Count

# 同时获取作者和对应的图书数量,过滤出有书的作者
authors_with_books = Author.objects.annotate(book_count=Count('book')).filter(book_count__gt=0)

这种方式不仅能得到符合要求的作者,还能直接通过author.book_count获取该作者的图书数量,不用再额外发起查询。

结合分页使用

把过滤后的查询集传给Paginator,分页逻辑就完全正常了:

from django.core.paginator import Paginator
from django.shortcuts import render

def author_list(request):
    # 用上面任意一种方法获取过滤后的查询集
    authors_queryset = Author.objects.exclude(book__isnull=True)
    # 每页显示10个作者
    paginator = Paginator(authors_queryset, 10)
    page_number = request.GET.get('page')
    page_obj = paginator.get_page(page_number)
    
    return render(request, 'author_list.html', {'page_obj': page_obj})

模板里直接循环page_obj即可,不用再判断作者是否有书:

{% for author in page_obj %}
    <div class="author-item">
        <h3>{{ author.name }}</h3>
        {# 如果用方法二,还可以直接显示图书数量 #}
        {# <p>图书数量:{{ author.book_count }}</p> #}
    </div>
{% endfor %}

{# 分页导航代码 #}
<div class="pagination">
    <span class="step-links">
        {% if page_obj.has_previous %}
            <a href="?page=1">&laquo; 首页</a>
            <a href="?page={{ page_obj.previous_page_number }}">上一页</a>
        {% endif %}

        <span class="current">
            第 {{ page_obj.number }} 页 / 共 {{ page_obj.paginator.num_pages }} 页
        </span>

        {% if page_obj.has_next %}
            <a href="?page={{ page_obj.next_page_number }}">下一页</a>
            <a href="?page={{ page_obj.paginator.num_pages }}">末页 &raquo;</a>
        {% endif %}
    </span>
</div>

内容的提问来源于stack exchange,提问作者Korab Duklini

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 16:50:22