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

向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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 21:36:05