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

Django模板列表视图含分页,如何获取所有分页选中的复选框对象

Django分页视图跨页保存复选框选中状态的解决方案

下面提供三种实用方案,覆盖不同场景需求:

方案1:前端本地存储(LocalStorage)

适合无需登录、仅在当前浏览器会话中保存选中状态的场景,实现简单。

  • 核心逻辑:
    • 页面加载时读取本地存储的选中ID,恢复当前页复选框状态
    • 复选框点击时更新本地存储的ID列表
    • 提交时把本地存储的ID存入隐藏字段传给后端

模板与JS代码示例

<form method="post" action="{% url 'submit-selected' %}">
    {% csrf_token %}
    <input type="hidden" id="selected-ids" name="selected_ids">
    
    {% for item in page_obj %}
    <div>
        <input type="checkbox" class="item-checkbox" value="{{ item.id }}">
        {{ item.name }}
    </div>
    {% endfor %}

    <!-- 分页控件 -->
    <div class="pagination">
        {% if page_obj.has_previous %}
        <a href="?page={{ page_obj.previous_page_number }}">上一页</a>
        {% endif %}
        <span>{{ page_obj.number }}/{{ page_obj.paginator.num_pages }}</span>
        {% if page_obj.has_next %}
        <a href="?page={{ page_obj.next_page_number }}">下一页</a>
        {% endif %}
    </div>

    <button type="submit" id="submit-btn">提交选中项</button>
</form>

<script>
// 页面加载恢复选中状态
document.addEventListener('DOMContentLoaded', () => {
    const selectedIds = JSON.parse(localStorage.getItem('selectedItems')) || [];
    document.querySelectorAll('.item-checkbox').forEach(box => {
        if (selectedIds.includes(box.value)) box.checked = true;
    });
});

// 复选框状态变更时更新本地存储
document.querySelectorAll('.item-checkbox').forEach(box => {
    box.addEventListener('change', () => {
        let selectedIds = JSON.parse(localStorage.getItem('selectedItems')) || [];
        if (box.checked) {
            !selectedIds.includes(box.value) && selectedIds.push(box.value);
        } else {
            selectedIds = selectedIds.filter(id => id !== box.value);
        }
        localStorage.setItem('selectedItems', JSON.stringify(selectedIds));
    });
});

// 提交时把选中ID写入隐藏字段
document.getElementById('submit-btn').addEventListener('click', () => {
    const selectedIds = JSON.parse(localStorage.getItem('selectedItems')) || [];
    document.getElementById('selected-ids').value = JSON.stringify(selectedIds);
});
</script>

后端视图处理

import json
from django.shortcuts import redirect, render
from .models import YourModel

def submit_selected(request):
    if request.method == 'POST':
        selected_ids = json.loads(request.POST.get('selected_ids', '[]'))
        selected_objects = YourModel.objects.filter(id__in=selected_ids)
        # 这里写你的业务逻辑,比如批量操作
        return redirect('success-page')
    return redirect('item-list')

方案2:URL参数传递选中ID

适合对安全性要求不高、需要分享选中状态链接的场景,无需JS即可实现。

  • 核心逻辑:切换分页时把已选中的ID拼到分页链接的URL参数里,页面加载时解析参数恢复选中状态。

模板代码示例

<form method="post" action="{% url 'submit-selected' %}">
    {% csrf_token %}
    {% for item in page_obj %}
    <div>
        <input type="checkbox" name="selected" value="{{ item.id }}"
            {% if item.id|stringformat:"s" in request.GET.getlist('selected') %}checked{% endif %}>
        {{ item.name }}
    </div>
    {% endfor %}

    <!-- 带选中ID的分页链接 -->
    <div class="pagination">
        {% if page_obj.has_previous %}
        {% with selected_ids=request.GET.getlist('selected') %}
        <a href="?page={{ page_obj.previous_page_number }}&{% for id in selected_ids %}selected={{ id }}&{% endfor %}">上一页</a>
        {% endwith %}
        {% endif %}

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

        {% if page_obj.has_next %}
        {% with selected_ids=request.GET.getlist('selected') %}
        <a href="?page={{ page_obj.next_page_number }}&{% for id in selected_ids %}selected={{ id }}&{% endfor %}">下一页</a>
        {% endwith %}
        {% endif %}
    </div>

    <button type="submit">提交选中项</button>
</form>

后端视图处理

from django.shortcuts import redirect, render
from .models import YourModel

def item_list(request):
    # 分页逻辑(略)
    selected_ids = request.GET.getlist('selected')
    context = {'page_obj': page_obj, 'selected_ids': selected_ids}
    return render(request, 'item_list.html', context)

def submit_selected(request):
    if request.method == 'POST':
        selected_ids = request.POST.getlist('selected')
        selected_objects = YourModel.objects.filter(id__in=selected_ids)
        # 业务逻辑处理
        return redirect('success-page')
    return redirect('item-list')

方案3:会话(Session)存储选中ID

适合登录用户,选中状态可跨浏览器标签页保持,数据存在服务端更安全。

  • 核心逻辑:用AJAX把复选框状态变更同步到服务端Session,切换分页时从Session读取已选中ID恢复状态,提交时直接从Session取数据。

前端AJAX代码(嵌入模板)

<form method="post" action="{% url 'submit-selected' %}">
    {% csrf_token %}
    {% for item in page_obj %}
    <div>
        <input type="checkbox" class="item-checkbox" value="{{ item.id }}"
            {% if item.id|stringformat:"s" in selected_ids %}checked{% endif %}>
        {{ item.name }}
    </div>
    {% endfor %}

    <!-- 分页控件(正常写法即可) -->
    <div class="pagination">
        {% if page_obj.has_previous %}
        <a href="?page={{ page_obj.previous_page_number }}">上一页</a>
        {% endif %}
        <span>{{ page_obj.number }}/{{ page_obj.paginator.num_pages }}</span>
        {% if page_obj.has_next %}
        <a href="?page={{ page_obj.next_page_number }}">下一页</a>
        {% endif %}
    </div>

    <button type="submit">提交选中项</button>
</form>

<script>
const csrfToken = document.querySelector('[name=csrfmiddlewaretoken]').value;
document.querySelectorAll('.item-checkbox').forEach(box => {
    box.addEventListener('change', () => {
        fetch('/update-selected/', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'X-CSRFToken': csrfToken
            },
            body: JSON.stringify({
                item_id: box.value,
                action: box.checked ? 'add' : 'remove'
            })
        });
    });
});
</script>

后端视图代码

import json
from django.http import JsonResponse
from django.shortcuts import redirect, render
from .models import YourModel

def update_selected(request):
    if request.method == 'POST':
        data = json.loads(request.body)
        item_id = data['item_id']
        action = data['action']

        # 初始化Session中的选中列表
        if 'selected_items' not in request.session:
            request.session['selected_items'] = []
        
        selected_list = request.session['selected_items']
        if action == 'add' and item_id not in selected_list:
            selected_list.append(item_id)
        elif action == 'remove' and item_id in selected_list:
            selected_list.remove(item_id)
        
        request.session['selected_items'] = selected_list
        return JsonResponse({'status': 'ok'})
    return JsonResponse({'status': 'error'}, status=400)

def item_list(request):
    # 分页逻辑(略)
    selected_ids = request.session.get('selected_items', [])
    context = {'page_obj': page_obj, 'selected_ids': selected_ids}
    return render(request, 'item_list.html', context)

def submit_selected(request):
    if request.method == 'POST':
        selected_ids = request.session.get('selected_items', [])
        selected_objects = YourModel.objects.filter(id__in=selected_ids)
        # 业务逻辑处理后清空Session
        request.session.pop('selected_items', None)
        return redirect('success-page')
    return redirect('item-list')

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.10 21:10:00