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
相关产品推荐
相关产品推荐

