向Django视图提交POST表单时如何实现分页功能
Django POST表单分页参数丢失解决方案
你的问题核心是分页跳转走GET请求,但筛选参数仅从POST中读取,导致翻页时筛选条件丢失,以下是3种可行解决方案:
方案1:将表单改为GET提交(搜索场景优先推荐)
搜索属于幂等操作,用GET提交更符合HTTP规范,且参数会自动携带在URL中,天然支持分页、分享链接等场景。
1.1 修改视图代码
将筛选参数的取值来源从request.POST改为request.GET:
def maintenance_issue_search(request): # 从GET取筛选参数 start_date = request.GET.get('date') end_date = request.GET.get('date1') status = request.GET.getlist('select_status') # 增加参数合法性校验,避免空参数报错 if not all([start_date, end_date, status]): all_issue_list = MaintenanceIssue.objects.none() else: all_issue_list = MaintenanceIssue.objects.filter( register_dt__date__range=(start_date, end_date), issue_status__in = status)\ .order_by('-issue_status','register_dt') page = request.GET.get('page', 1) # 原有分页逻辑保持不变 paginator = Paginator(all_issue_list, 10) try: issue_list = paginator.page(page) except PageNotAnInteger: issue_list = paginator.page(1) except EmptyPage: issue_list = paginator.page(paginator.num_pages) context = {'issue_list':issue_list, 'start_date':start_date, 'end_date':end_date, 'status':status} return render(request, 'maintenance/maintenanceIssueList.html', context)
1.2 修改表单模板
修改表单属性,移除POST相关配置:
<!-- 把method改为get,移除不需要的enctype和csrf_token --> <form action="{% url 'maintenance_issue_search' %}" method="get" id="form" name="form"> <!-- 删掉{% csrf_token %}这一行 --> <div style="text-align:left;" class="form-row"> <!-- 原有表单控件保持不变 --> ... </div> </form>
1.3 修改分页链接,拼接筛选参数
首先自定义一个模板过滤器,用于移除URL参数中的page字段,避免重复:
# 在你app的templatetags目录下新建custom_filters.py from django import template register = template.Library() @register.filter def remove_page_param(querydict): q = querydict.copy() q.pop('page', None) return q.urlencode()
然后修改分页部分的链接,拼接现有筛选参数:
<!-- 顶部模板先引入自定义过滤器 --> {% load custom_filters %} ... <!--Pagination--> {% if issue_list.has_other_pages %} <ul class="table-pagination"> {% if issue_list.has_previous %} <li><a href="?page=1&{{ request.GET|remove_page_param }}">First</a></li> <li><a href="?page={{ issue_list.previous_page_number }}&{{ request.GET|remove_page_param }}">Previous</a></li> {% endif %} <span class="current"> Page {{ issue_list.number }} of {{ issue_list.paginator.num_pages }} </span> {% if issue_list.has_next %} <li><a href="?page={{ issue_list.next_page_number }}&{{ request.GET|remove_page_param }}">Next></a></li> <li><a href="?page={{ issue_list.paginator.num_pages }}&{{ request.GET|remove_page_param }}">Last></a></li> {% endif %} </ul> {% endif %}
方案2:保留POST提交,用Session存储筛选参数
如果业务场景必须使用POST提交,可以将用户的筛选条件存在Session中,翻页时直接从Session读取参数:
def maintenance_issue_search(request): # 有POST提交时更新Session中的筛选条件 if request.method == "POST": request.session['start_date'] = request.POST.get('date') request.session['end_date'] = request.POST.get('date1') request.session['select_status'] = request.POST.getlist('select_status') # 从Session读取筛选条件 start_date = request.session.get('start_date') end_date = request.session.get('end_date') status = request.session.get('select_status', []) # 原有查询、分页逻辑保持不变 if not all([start_date, end_date, status]): all_issue_list = MaintenanceIssue.objects.none() else: all_issue_list = MaintenanceIssue.objects.filter( register_dt__date__range=(start_date, end_date), issue_status__in = status)\ .order_by('-issue_status','register_dt') page = request.GET.get('page', 1) # 后续分页、返回逻辑不变 ...
注意:该方案存在多标签页参数冲突、Session过期后参数丢失的问题,仅适合小范围内部系统使用。
方案3:JS动态提交表单实现翻页
通过JS拦截分页按钮点击事件,把页码注入表单后提交,保证每次翻页都是POST请求:
3.1 表单新增隐藏页码字段
<form action="{% url 'maintenance_issue_search' %}" method="POST" enctype="multipart/form-data" id="form" name="form"> {% csrf_token %} <!-- 新增隐藏的page字段 --> <input type="hidden" name="page" id="page_input" value="1"> ... </form>
3.2 分页按钮绑定点击事件
<!--Pagination--> {% if issue_list.has_other_pages %} <ul class="table-pagination"> {% if issue_list.has_previous %} <li><a href="javascript:void(0);" data-page="1" class="page_btn">First</a></li> <li><a href="javascript:void(0);" data-page="{{ issue_list.previous_page_number }}" class="page_btn">Previous</a></li> {% endif %} <span class="current"> Page {{ issue_list.number }} of {{ issue_list.paginator.num_pages }} </span> {% if issue_list.has_next %} <li><a href="javascript:void(0);" data-page="{{ issue_list.next_page_number }}" class="page_btn">Next></a></li> <li><a href="javascript:void(0);" data-page="{{ issue_list.paginator.num_pages }}" class="page_btn">Last></a></li> {% endif %} </ul> {% endif %} <!-- 新增JS逻辑 --> <script> document.querySelectorAll('.page_btn').forEach(btn => { btn.addEventListener('click', function() { document.getElementById('page_input').value = this.dataset.page; document.getElementById('form').submit(); }) }) </script>
3.3 视图修改页码取值来源
page = request.POST.get('page', 1)
内容的提问来源于stack exchange,提问作者HudsonBarroso
相关产品推荐
相关产品推荐

