Django集成django-filter与分页功能时,点击下一页仍显示第一页搜索结果的问题排查
问题定位
核心错误出在模板分页链接的URL拼接逻辑:
- 原代码中分页链接写为
?caption={{caption}}&?page={{result.next_page_number}},在参数分隔符&之后额外多写了一个?,导致生成的查询串不符合URL规范。 - 根据URL解析规则,第一个
?之后的内容才是查询参数段,所有参数需以key=value的格式通过&分隔。多余的?会让服务端解析请求参数时,将参数键识别为?page而非page,因此视图中request.GET.get('page')永远取不到有效值,返回None,分页逻辑自然失效,这也和你观察到的异常URL(?caption=tom&?page=2)完全对应。 - 额外隐患:视图中直接通过
request.GET['caption']强取参数,一旦用户无筛选关键词直接访问分页链接,会直接触发KeyError导致页面崩溃。
修复方案
修正分页链接的URL格式
去掉拼接时多余的?,修正后的模板代码:
{% if result.has_next %} <a href="?caption={{ caption }}&page={{ result.next_page_number }}"> <button>See more results</button> </a> {% endif %}
长期优化建议:如果后续会新增更多筛选条件,不要硬编码每个筛选参数的拼接逻辑,可以直接使用Django内置的{% querystring %}模板标签自动继承所有现有GET参数,仅替换分页页码值,从根源上避免符号写错、漏传参数的问题。
优化视图的参数取值兼容性
将强取参数的逻辑替换为带默认值的安全取值,避免异常:
def search(request): queryset = Video.objects.all() filterset = VideoFilter(request.GET, queryset=queryset) if filterset.is_valid(): queryset = filterset.qs paginator = Paginator(queryset, 2) page_number = request.GET.get('page') page_result = paginator.get_page(page_number) return render(request, 'search.html', { 'result': page_result, 'caption': request.GET.get('caption', ''), })
验证效果
修改完成后,点击下一页生成的URL结构会变为/search/?caption=tom&page=2,服务端可以正常解析到page参数,对应分页的筛选结果会正常加载,不会出现整页重复第一页内容的问题。
内容的提问来源于stack exchange,提问作者Asif Biswas
相关产品推荐
相关产品推荐

