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

Django分页上一页按钮点击跳转下一页异常求解

Django分页点击上一页反向跳转下一页问题修复

问题根因

  • 标签属性误用:<button>标签不支持method属性,提交方法必须定义在外层<form>标签上,写在button上的method属性无任何效果
  • 同名表单参数冲突:上一页、下一页对应的name="page_no"隐藏输入框同属一个表单域,当页面不在首页/尾页时,两个隐藏域会同时存在,表单提交时会携带两个同名的page_no参数。Django的request.POST.get()方法遇到同名参数时默认取最后一个值,也就是下一页的页码,因此不管点击哪个按钮,后端拿到的都是下一页页码,导致跳转逻辑错误
  • 视图逻辑顺序错误:当前视图先从POST取页码生成分页对象,再判断请求方法,首次GET访问页面时POST中无页码参数,会触发取值异常

排查思路

  • 打开浏览器开发者工具,切换到Network面板,点击上一页按钮查看请求的Form Data,确认提交的page_no实际值,可直接定位参数冲突问题
  • 检查HTML结构,确认两个分页按钮和对应隐藏域是否被同一个<form>包裹,未做参数隔离
  • 在视图层打印全量request.POST数据,验证后端接收到的页码参数是否符合预期

修复方案

方案1:拆分独立表单隔离参数(推荐)

给上一页、下一页按钮分别包裹独立的form标签,把method属性移到form上,每个表单内只放对应按钮的隐藏域,提交时只会携带当前表单内的参数,从根源避免同名冲突。注意Django POST请求必须携带CSRF令牌,否则会返回403错误。
模板代码修改如下:

{% if page_obj.has_previous %}
<form method="post" style="display: inline-block;">
    {% csrf_token %}
    <button type="submit" class="action-btn checkRequired Submit" name="action" value="Submit">previous</button>
    <input type="hidden" name="page_no" value="{{ page_obj.previous_page_number }}">
</form>
{% endif %}

<span>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</span>

{% if page_obj.has_next %}
<form method="post" style="display: inline-block;">
    {% csrf_token %}
    <button type="submit" class="action-btn checkRequired Submit" name="action" value="Submit">next</button>
    <input type="hidden" name="page_no" value="{{ page_obj.next_page_number }}">    
</form>
{% endif %}

同步调整视图逻辑,给页码设置默认值,调整逻辑顺序兼容GET访问:

def practise(request):
    questions_list = Question.objects.all().order_by('id')
    paginator = Paginator(questions_list, 1)
    # 默认加载第一页
    page_number = 1

    if request.method == "POST":
        page_number = request.POST.get('page_no', 1)
        answer = request.POST.get('answer')
        difficulty = request.POST.get('myRange')
        surety = request.POST.get('surety')
        # 此处补充答题相关业务逻辑

    page_obj = paginator.get_page(page_number)
    return render(request, "try.html", {'page_obj': page_obj})

方案2:通过按钮value传参,无需隐藏域

如果不想拆分多个表单,可以去掉隐藏的page_no输入框,直接把页码写在按钮的value属性上,给两个按钮设置不同的name属性,后端根据请求参数中存在的按钮名判断点击行为,取对应页码即可。
模板代码:

<form method="post">
    {% csrf_token %}
    {% if page_obj.has_previous %}
    <button type="submit" class="action-btn checkRequired Submit" name="prev_page" value="{{ page_obj.previous_page_number }}">previous</button>
    {% endif %}

    <span>Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}</span>

    {% if page_obj.has_next %}
    <button type="submit" class="action-btn checkRequired Submit" name="next_page" value="{{ page_obj.next_page_number }}">next</button>    
    {% endif %}

    <!-- 其他答题相关表单字段放在这里 -->
</form>

后端取值逻辑调整:

def practise(request):
    questions_list = Question.objects.all().order_by('id')
    paginator = Paginator(questions_list, 1)
    page_number = 1

    if request.method == "POST":
        if 'prev_page' in request.POST:
            page_number = request.POST.get('prev_page')
        elif 'next_page' in request.POST:
            page_number = request.POST.get('next_page')
        # 处理答题参数
        answer = request.POST.get('answer')
        difficulty = request.POST.get('myRange')
        surety = request.POST.get('surety')

    page_obj = paginator.get_page(page_number)
    return render(request, "try.html", {'page_obj': page_obj})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.03 07:30:52