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

Django切换分页、排序时搜索筛选参数丢失如何修复?

问题根源

你的分页链接仅携带了page参数,原有筛选参数(location、category、look_for)、排序参数(sort_by)、分页数量参数(paginate_by)都没有被携带到新的URL中,后端接收到请求后没有筛选条件,自然返回全部数据。

修复步骤

第一步:修改视图层,传递保留参数到模板

修改SearchView的get_context_data方法,将除page之外的所有GET请求参数编码后传到模板上下文:

def get_context_data(self, *args, **kwargs):
    context = super(SearchView, self).get_context_data(*args, **kwargs)
    # 复制当前GET参数
    query_params = self.request.GET.copy()
    # 移除page参数,避免后续拼接重复
    query_params.pop('page', None)
    # 编码为URL参数字符串传到模板
    context['query_params'] = query_params.urlencode()
    return context

第二步:修改模板分页链接,拼接保留参数

把所有分页的href属性都修改为以下格式,先拼接保留的筛选参数,再加page参数:

{% if is_paginated %}
{% if page_obj.has_previous %}
  <li>
    <a href="?{% if query_params %}{{ query_params }}&{% endif %}page=1" aria-label="First">
      <span aria-hidden="true">First</span>
    </a>
  </li>
  <li>
    <a href="?{% if query_params %}{{ query_params }}&{% endif %}page={{ page_obj.previous_page_number }}" aria-label="Previous">
      <span aria-hidden="true">&laquo;</span>
    </a>
  </li>
{% endif %}
{% for num in page_obj.paginator.page_range %}
  {% if page_obj.number == num %}
    <li class="active"><a href="?{% if query_params %}{{ query_params }}&{% endif %}page={{num}}">{{num}}</a></li>
  {% elif num > page_obj.number|add:'-3' and num < page_obj.number|add:'3'%}
    <li><a href="?{% if query_params %}{{ query_params }}&{% endif %}page={{num}}">{{num}}</a></li>
  {% endif %}
{% endfor %}
{% if page_obj.has_next %}
  <li>
    <a href="?{% if query_params %}{{ query_params }}&{% endif %}page={{ page_obj.next_page_number }}" aria-label="Next">
      <span aria-hidden="true">&raquo;</span></a>
  <li>
    <a href="?{% if query_params %}{{ query_params }}&{% endif %}page={{ page_obj.paginator.num_pages }}" aria-label="Last">
      <span aria-hidden="true">Last</span></a>
{% endif %}
{%endif%}

这个修改同时解决了切换排序、调整每页数量时的参数丢失问题,因为所有除page外的参数都会被保留。

代码优化建议

  • 简化get_queryset逻辑,无需嵌套多层判断,动态构建查询条件即可:
def get_queryset(self):
    queryset = super().get_queryset()
    # 逐个判断参数是否有效,有效就加筛选
    location = self.request.GET.get('location', '').strip()
    category = self.request.GET.get('category', '').strip()
    look_for = self.request.GET.get('look_for', '').strip()
    if location:
        queryset = queryset.filter(city__icontains=location)
    if category:
        queryset = queryset.filter(category__slug=category)
    if look_for:
        queryset = queryset.filter(property_status=look_for)
    return queryset
  • 优化get_paginate_by的类型校验,避免传入非数字参数报错:
def get_paginate_by(self, queryset):
    paginate_by = self.request.GET.get("paginate_by", self.paginate_by)
    try:
        return int(paginate_by)
    except (ValueError, TypeError):
        return self.paginate_by
  • 排序规则可以用字典映射替代多层if elif,更易维护:
def get_ordering(self):
    sort_map = {
        "Name": "-title",
        "Price": "-price",
        "Date": "-pub_date"
    }
    sort_by = self.request.GET.get('sort_by')
    return sort_map.get(sort_by, self.ordering)

内容的提问来源于stack exchange,提问作者Farshad Zargari

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 23:42:00