解决 Django 分页器在点击页码时丢失搜索过滤条件的问题,关键在于分页链接必须保留原始 GET 参数(如 g_searched),否则请求会退化为无过滤的全量查询。
解决 django 分页器在点击页码时丢失搜索过滤条件的问题,关键在于分页链接必须保留原始 get 参数(如 `g_searched`),否则请求会退化为无过滤的全量查询。
在你的 group_search.html 模板中,当前分页链接(如 ?page=2)仅传递了 page 参数,而丢弃了用户输入的 g_searched 搜索关键词。当用户点击“第2页”时,视图收到的是一个不含 g_searched 的 GET 请求,导致 request.GET.get("g_searched", 1) 返回默认值 1,进而执行 Binders.objects.filter(Q(group_id__contains=1)) —— 这不仅逻辑错误,更可能匹配大量无关记录,甚至因 1 是常见数字而返回全表数据。
✅ 正确做法:将原始搜索参数持久化到所有分页链接中。
推荐使用 Django 内置的 urlencode 过滤器动态构建带参 URL:
<!-- 在 group_search.html 中替换整个 pagination <ul> 块 -->
<nav aria-label="Page navigation example"><ul class="pagination justify-content-center">
{% if page_obj.has_previous %}
<li class="page-item">
<a class="page-link" href="?g_searched=%7B%7B%20g_searched%7Curlencode%20%7D%7D&page=1">First</a>
</li>
<li class="page-item">
<a class="page-link" href="?g_searched=%7B%7B%20g_searched%7Curlencode%20%7D%7D&page=%7B%7B%20page_obj.previous_page_number%20%7D%7D">Previous</a>
</li>
{% endif %}
{% for num in page_obj.paginator.page_range %}
<li class="page-item {% if page_obj.number == num %}active{% endif %}">
<a class="page-link" href="?g_searched=%7B%7B%20g_searched%7Curlencode%20%7D%7D&page=%7B%7B%20num%20%7D%7D">{{ num }}</a>
</li>
{% endfor %}
{% if page_obj.has_next %}
<li class="page-item">
<a class="page-link" href="?g_searched=%7B%7B%20g_searched%7Curlencode%20%7D%7D&page=%7B%7B%20page_obj.next_page_number%20%7D%7D">Next</a>
</li>
<li class="page-item">
<a class="page-link" href="?g_searched=%7B%7B%20g_searched%7Curlencode%20%7D%7D&page=%7B%7B%20page_obj.paginator.num_pages%20%7D%7D">Last</a>
</li>
{% endif %}
</ul></nav>
? 说明:{{ g_searched|urlencode }} 确保特殊字符(如空格、&、/)被安全编码,避免 URL 解析错误;page_obj.paginator.page_range 比 "a" * num_pages 更语义清晰且健壮;active 类增强用户体验。
? 同时优化 views.py(提升健壮性与可维护性):
def group_search(request):
g_searched = request.GET.get("g_searched", "").strip() # 防空格输入,避免模糊匹配
group_searched = Binders.objects.all()
if g_searched: # 仅当有有效搜索词时才过滤
group_searched = group_searched.filter(group_id__icontains=g_searched) # 推荐 icontains 替代 contains
paginator = Paginator(group_searched, 20)
page_number = request.GET.get('page')
page_obj = paginator.get_page(page_number)
context = {
'g_searched': g_searched,
'page_obj': page_obj,
'group_count': group_searched.count(), # 使用过滤后 QuerySet 的 count()
}
return render(request, "group_search.html", context)
⚠️ 注意事项:
- 不要依赖 request.session['csv_searched'] 来维持搜索状态——它与分页无关,且 session 不应替代 URL 参数的显式传递;
- 若未来增加多字段过滤(如日期范围、状态选择),应统一通过 request.GET 获取并拼接到所有分页链接中;
- 对于复杂筛选场景,可封装为工具函数(如 get_pagination_url(request, page_num))复用逻辑;
- 始终对用户输入做 .strip() 和空值判断,防止意外全表扫描。
通过以上改造,分页链接将始终携带当前搜索上下文,确保每一页都基于相同的过滤结果集进行切片,彻底解决“翻页即重置”的核心问题。











