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

如何为Django搜索结果实现分页功能并优化search视图代码

Django搜索结果分页实现与视图优化方案

分页实现核心逻辑

你已经在index页实现了基础分页,搜索结果的分页逻辑完全通用——Django内置的Paginator支持接收任意QuerySet对象,不管是全量数据还是多条件过滤后的结果,都可以直接传入分页。

先修复现有代码的2个bug

在加分页之前先修正两个过滤逻辑的错误,否则搜索结果本身就不对:

  • job_type过滤条件错误传入了整个选项元组job_type_choices作为匹配值,应该使用前端传回的job_type参数
  • industry过滤条件同理,错误传入了industry_choices,应该使用前端传回的industry参数

视图层改造步骤

  1. 确保文件顶部已导入分页类:
    from django.core.paginator import Paginator
    
  2. 所有过滤逻辑执行完成后,追加和index页完全一致的分页代码,把最终分页后的对象传给模板即可。

优化后的完整search视图代码

def search(request):
    # 初始化查询集,和列表页保持一致:只展示已发布职位,按发布时间倒序
    queryset = Job.objects.order_by('-publishing_date').filter(is_published=True)

    # 一次性提取所有搜索参数,无需手动判断key是否存在
    keywords = request.GET.get('keywords')
    state = request.GET.get('state')
    job_type = request.GET.get('job_type')
    industry = request.GET.get('industry')
    salary = request.GET.get('salary')

    # 按需追加过滤条件
    if keywords:
        queryset = queryset.filter(description__icontains=keywords)
    if state:
        queryset = queryset.filter(location__iexact=state)
    if job_type:
        queryset = queryset.filter(job_type__iexact=job_type)
    if industry:
        queryset = queryset.filter(industry__icontains=industry)
    if salary:
        queryset = queryset.filter(salary__lte=salary)

    # 执行分页:每页6条,和列表页配置统一
    paginator = Paginator(queryset, 6)
    page_num = request.GET.get('page')
    paged_jobs = paginator.get_page(page_num)

    context = {
        'location_choices': location_choices,
        'salary_choices': salary_choices,
        'job_type_choices': job_type_choices,
        'industry_choices': industry_choices,
        'jobs': paged_jobs,
        'values': request.GET,
    }
    return render(request, 'jobs/search.html', context)

模板层适配注意点

翻页时必须保留原有搜索参数,否则点击下一页后筛选条件会丢失,直接回到全量职位列表。不需要手动逐个拼接参数,用Django自带的urlencode方法即可自动生成带所有现有GET参数的查询串,分页组件示例:

<div class="pagination-wrapper">
    {% if jobs.has_previous %}
    <a href="?page={{ jobs.previous_page_number }}&{{ request.GET.urlencode }}" class="page-btn">上一页</a>
    {% endif %}

    {% for num in jobs.paginator.page_range %}
        {% if jobs.number == num %}
        <span class="page-btn active">{{ num }}</span>
        {% else %}
        <a href="?page={{ num }}&{{ request.GET.urlencode }}" class="page-btn">{{ num }}</a>
        {% endif %}
    {% endfor %}

    {% if jobs.has_next %}
    <a href="?page={{ jobs.next_page_number }}&{{ request.GET.urlencode }}" class="page-btn">下一页</a>
    {% endif %}
</div>

视图优化说明

原来的写法可以正常运行,调整后更符合Django的常规写法,可维护性更高:

  • 去掉冗余的if 'xxx' in request.GET判断:request.GET.get('xxx')在key不存在时默认返回None,空字符串、None在if判断中都属于假值,原有判空逻辑完全不受影响,代码量减少近三分之一
  • 统一基础过滤规则:原搜索逻辑没有加is_published=True过滤,会把后台未发布的职位也暴露在搜索结果中,和列表页规则对齐后避免数据泄露
  • 参数提取前置:所有搜索参数在过滤逻辑前一次性取出,代码结构更清晰,不会出现取值、过滤逻辑混写的情况
  • 分页逻辑和列表页完全对齐:后续如果要调整每页展示数量,只需要把6抽成全局配置项即可,不需要修改两处代码

额外说明:Django的QuerySet是懒加载的,链式调用filter的时候不会真正执行数据库查询,只有当Paginator取对应页数据、或者模板遍历职位列表时才会生成带LIMIT/OFFSET的分页SQL,不会出现查询全表的性能问题。


内容的提问来源于stack exchange,提问作者QwertyC-137

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 14:12:17